AOP(Aspect Oriented Programming) 面向切面编程,是目前软件开发中的一个热点,是Spring框架内容,利用AOP能够对业务逻辑的各个部分隔离,从而使的业务逻辑各部分的耦合性下降,提升程序的可重用性,提高开发效率。java
AOP实现原理是java动态代理,可是jdk的动态代理必须实现接口,因此spring的aop是用cglib这个库实现的,cglib使用里asm这个直接操纵字节码的框架,因此能够作到不使用接口的状况下实现动态代理。正则表达式
AOP是处理一些横切行问题。这些横切性问题不会影响到主逻辑的实现,可是会散落到代码的各个部分,难以维护。AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。spring
OOP面向对象编程,针对业务处理过程的实体及其属性和行为进行抽象封装,以得到更加清晰高效的逻辑单元划分。而AOP则是针对业务处理过程当中的切面进行提取,它所面对的是处理过程的某个步骤或阶段,以得到逻辑过程的中各部分之间低耦合的隔离效果。这两种设计思想在目标上有着本质的差别。编程
经过下面的图能够清晰的理解AOP与OOP的区别:缓存
AOP中的Joinpoint能够有多种类型:构造方法调用,字段的设置和获取,方法的调用,方法的执行,异常的处理执行,类的初始化。也就是说在AOP的概念中咱们能够在上面的这些Joinpoint上织入咱们自定义的Advice,可是在Spring中却没有实现上面全部的joinpoint,确切的说,Spring只支持方法执行类型的Joinpoint性能优化
pom.xmlbash
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
复制代码
定义一个通用接口,全部实现此接口的类都有一个咸鱼方法和一个测试aop的方法app
public interface HelloWorld {
void saltedFish();
void testPrintTime();
}
复制代码
实现1框架
public class HelloWorldImpl1 implements HelloWorld{
@Override
public void saltedFish() {
System.out.println("this is a salted fish =========== 1");
}
@Override
public void testPrintTime() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testPrintTime 1=============111111111");
}
}
复制代码
实现2ide
public class HelloWorldImpl2 implements HelloWorld{
@Override
public void saltedFish() {
System.out.println("this is a salted fish =========== 2");
}
@Override
public void testPrintTime() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("testPrintTime 2=============22222222");
}
}
复制代码
定义一个Advice,实如今链接点以前以后该干的事
public class TimeHandler implements MethodBeforeAdvice, AfterReturningAdvice {
Long before = 0L;
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
Long after = System.currentTimeMillis();
System.out.println("==========代理后time, " + after + " ======= 间隔: " + (after - before) + "==========");
}
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
before = System.currentTimeMillis();
System.out.println("==========代理前time:" + before + "===========");
}
}
复制代码
经过xml配置切面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义 -->
<bean id="h1" class="com.example.demo.aop.HelloWorldImpl1"></bean>
<bean id="h2" class="com.example.demo.aop.HelloWorldImpl2"></bean>
<!-- 定义advice -->
<bean id="timeHandler" class="com.example.demo.aop.TimeHandler"></bean>
<!-- 定义point cut -->
<bean id="timePointCut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*testPrintTime"></property>
</bean>
<!-- 切面 关联切入点与通知 -->
<bean id="timeHandlerAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="timeHandler"></property>
<property name="pointcut" ref="timePointCut"></property>
</bean>
<!-- 设置代理-->
<bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的对象 -->
<property name="target" ref="h1"></property>
<!-- 使用的切面 -->
<property name="interceptorNames" value="timeHandlerAdvisor"></property>
<!-- 代理接口 -->
<property name="interfaces" value="com.example.demo.aop.HelloWorld"></property>
</bean>
<!-- 设置代理-->
<bean id="proxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理的对象 -->
<property name="target" ref="h2"></property>
<!-- 使用的切面 -->
<property name="interceptorNames" value="timeHandlerAdvisor"></property>
<!-- 代理接口 -->
<property name="interfaces" value="com.example.demo.aop.HelloWorld"></property>
</bean>
</beans>
复制代码
测试类
public class AOPTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("./application.xml");
HelloWorld helloWorld1 = (HelloWorld) applicationContext.getBean("proxy1");
HelloWorld helloWorld2 = (HelloWorld) applicationContext.getBean("proxy2");
helloWorld1.saltedFish();
System.out.println("---------------------");
helloWorld1.testPrintTime();
System.out.println("=======================");
helloWorld2.saltedFish();
System.out.println("---------------------");
helloWorld2.testPrintTime();
}
}
复制代码
打印
this is a salted fish =========== 1
---------------------
==========代理前time:1582477901748===========
testPrintTime 1=============111111111
==========代理后time, 1582477902750 ======= 间隔: 1002==========
=======================
this is a salted fish =========== 2
---------------------
==========代理前time:1582477902750===========
testPrintTime 2=============22222222
==========代理后time, 1582477903250 ======= 间隔: 500==========
复制代码
复制代码