什么是AOP?

AOP是面向切面编程。在我们正常开发完成后,是纵向的,可能会增加需要并且要求不改变原有的代码逻辑。那么我们就需要横向的把这个新的功能点插入到原来纵向结构中,这样既保证了原有业务不动,又能添加新的功能。

此外,这样的插入并非静态的,而是动态的,即在运行时,动态的将代码插入到类的指定方法,指定位置的编程思想就是AOP

因此,AOP并非Spring独有的,它是一种编程思想,只是说Spring的核心就是这一思想。

请注意,如果问到AOP,一定要说到动态代理,因为其本质就是动态代理。

如何在Spring中使用AOP

方式1:使用spring的API接口

即实现MethodBeforeAdvice和AfterReturningAdvice

  1. 导入依赖:

    1. <dependency>
    2. <groupId>org.aspectj</groupId>
    3. <artifactId>aspectjweaver</artifactId>
    4. <version>1.9.4</version>
    5. <scope>runtime</scope>
    6. </dependency>
  2. 添加头文件

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <beans>
    
  3. 类实现MethodBeforeAdvice来进行前置增强

    public class Log implements MethodBeforeAdvice {
     // method: 要执行的目标对象的方法
     // args: 参数
     // target: 目标对象
     @Override
     public void before(Method method, Object[] objects, Object target) throws Throwable {
         System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
     }
    }
    
  4. 类实现AfterReturningAdvice来进行后置增强

    public class AfterLog implements AfterReturningAdvice {
    
     @Override
     public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
         System.out.println("执行了" + method.getName() + "返回结果为:" + returnValue);
     }
    }
    
  5. 注册bean

     <bean id="userService" class="com.kuang.service.UserServiceImpl"></bean>
     <bean id="log" class="com.kuang.log.Log"></bean>
     <bean id="afterLog" class="com.kuang.log.AfterLog"></bean>
    
  6. 配置aop

      <aop:config>
          // 定义插入点
         <aop:pointcut expression="execution(* com.kuang.service.UserServiceImpl.*(..)" id="pointcut"/>
    
         // 将增强插入到切入点,分别是之前和之后
         <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
         <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
     </aop:config>
    
    1. 使用时,获取applicationContext, 获取service的bean对象,调用service里的方法,就会被自动增强。

      public class MyTest {
      public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
      
        userService.add();
      }
      }
      

方式2:自定义实现AOP

  1. 自定义一个类和方法: ```java public class DiyPointCut { public void before() {
    System.out.println("=====方法执行前=====");
    
    }
public void after() {
    System.out.println("=====方法执行后======");
}

}


2. 注册bean对象
```java
    <bean id="diy" class="com.kuang.diy.DiyPointCut">
    </bean>
  1. 通过aop配置进行切入
     <aop:config>
         <aop:aspect ref="diy">
             <aop:pointcut id="point" expression="execution(* com.kuang.service.UserService.*(..))"/>
             <aop:before method="before" pointcut-ref="point"/>
             <aop:after method="after" pointcut-ref="point"/>
         </aop:aspect>
     </aop:config>
    
    ps: 相对于方式1,更加简单一些。

方式3:通过注解实现AOP

  1. 添加自定义类,用@Aspect注解标注该类,用@Before或者@After来标注方法:

    @Aspect
    public class AnnotationPointCut {
    
     @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
     public void before() {
         System.out.println("这是注解,====执行前====");
     }
    
     @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
     public void after() {
         System.out.println("这是注解, ====执行后====");
     }
    }
    
  2. 注册该类的bean

     <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"></bean>
    
  3. 配置自动代理

     <aop:aspectj-autoproxy/>