Java Spring AOP

①导入Jar

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.aspectj</groupId>
  4. <artifactId>aspectjweaver</artifactId>
  5. <version>1.9.4</version>
  6. </dependency>
  7. </dependencies>

②配置文件开启aop文件头引用约束

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/aop
  8. http://www.springframework.org/schema/aop/spring-aop.xsd">
  9. </beans>

③抽象接口

  1. public interface UserService {
  2. void add();
  3. void delete();
  4. void update();
  5. void select();
  6. }

④实现类

  1. public class UserServiceImpl implements UserService {
  2. @Override
  3. public void add() {
  4. System.out.println("增加用户");
  5. }
  6. @Override
  7. public void delete() {
  8. System.out.println("删除用户");
  9. }
  10. @Override
  11. public void update() {
  12. System.out.println("更新用户");
  13. }
  14. @Override
  15. public void select() {
  16. System.out.println("查询用户");
  17. }
  18. }

一、通过 Spring API 实现

①添加前置后置方法

  1. public class AopBeforeConfigLog implements MethodBeforeAdvice {
  2. /**
  3. * method : 要执行的目标对象的方法
  4. * args : 被调用的方法的参数
  5. * target : 目标对象
  6. */
  7. @Override
  8. public void before(Method method, Object[] args, Object target) throws Throwable {
  9. System.out.println(target.getClass()+"===="+method.getName()+"被执行了");
  10. }
  11. }

②beans.xml

  1. <!--注册bean-->
  2. <bean id="userService" class="service.UserServiceImpl"/>
  3. <bean id="afterLog" class="aoptest.AopAfterConfigLog"/>
  4. <bean id="beforeAop" class="aoptest.AopBeforeConfigLog"/>
  5. <aop:config>
  6. <!--切入点 expression:表达式匹配要执行的方法-->
  7. <aop:pointcut id="cut" expression="execution(* service.UserServiceImpl.*(..))"/>
  8. <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
  9. <aop:advisor advice-ref="afterLog" pointcut-ref="cut"/>
  10. <aop:advisor advice-ref="beforeAop" pointcut-ref="cut"/>
  11. </aop:config>

③测试类

  1. public class AopAfterConfigLog implements AfterReturningAdvice {
  2. /**
  3. * method : 要执行的目标对象的方法
  4. * args : 被调用的方法的参数
  5. * result : 返回值
  6. * target : 被调用的目标对象
  7. */
  8. @Override
  9. public void afterReturning(Object result, Method method, Object[] args, Object target){
  10. System.out.println(target.getClass()+"===="+method.getName()+"被执行了"+"===返回值"+result);
  11. }
  12. }

④执行结果

⑤总结:

  • 切面:横切的点
  • 通知:切面完成的工作,其实就是一个方法
  • 目标:被通知的对象
  • expression="execution(* service.UserServiceImpl.*(..))" 这是一套固定的公式 *代表所有 这句话的意思就是service.UserServiceImpl下的所有方法都被切面了!

    二、自定义类来实现

    ①自定义被切入类

    ```java /*
  • 自定义类
  • */ public class MyDIYAopCut { public void before(){
    1. System.out.println("方法执行前前前前前前前前前前");
    } public void after(){
    1. System.out.println("方法执行后后后后后后后后后后");
    } } ```

    ②beans.xml

    ```xml

  1. <!--切入点之前执行,这里的方法名即是我们自定义类中的方法名-->
  2. <aop:before method="before" pointcut-ref="cut"/>
  3. <!--切入点之后执行,这里的方法名即是我们自定义类中的方法名-->
  4. <aop:before method="after" pointcut-ref="cut"/>

  1. <a name="b3iWn"></a>
  2. #### ③测试类不变,执行结果
  3. ![2021-08-31-23-18-37-009092.jpeg](https://cdn.nlark.com/yuque/0/2021/jpeg/396745/1630423178087-f3f6d1aa-df4a-4c0c-aba1-0064ab29e9ad.jpeg#clientId=uccf9371d-b338-4&from=ui&id=u9d5a4214&margin=%5Bobject%20Object%5D&name=2021-08-31-23-18-37-009092.jpeg&originHeight=341&originWidth=388&originalType=binary&ratio=1&size=19504&status=done&style=none&taskId=u069d5dde-c42a-4aba-b486-85683910d3e)
  4. <a name="caUy2"></a>
  5. #### ④总结:
  6. - 测试类的方法即是xml中method的方法名
  7. ![2021-08-31-23-18-37-121093.jpeg](https://cdn.nlark.com/yuque/0/2021/jpeg/396745/1630423131812-9dd4cd61-a1c4-4f39-839b-1f494e6cd103.jpeg#clientId=uccf9371d-b338-4&from=ui&id=u565fc29b&margin=%5Bobject%20Object%5D&name=2021-08-31-23-18-37-121093.jpeg&originHeight=302&originWidth=640&originalType=binary&ratio=1&size=16074&status=done&style=none&taskId=u4a9d268d-9475-469a-93cc-0fabfa89d1d)
  8. - 其他见xml中的注释!
  9. <a name="X4Z0w"></a>
  10. ### 三、使用注解实现
  11. <a name="TN9Yw"></a>
  12. #### ①自定义增强注解实现类
  13. ```java
  14. @Aspect
  15. public class MyAnnotationAopCut {
  16. @Before("execution(* service.UserServiceImpl.*(..))")
  17. public void before(){
  18. System.out.println("方法执行前");
  19. }
  20. @After("execution(* service.UserServiceImpl.*(..))")
  21. public void after(){
  22. System.out.println("方法执行后");
  23. }
  24. @Around("execution(* service.UserServiceImpl.*(..))")
  25. public void around(ProceedingJoinPoint point) throws Throwable {
  26. System.out.println("环绕前=="+point.getSignature());
  27. //执行
  28. Object proceed = point.proceed();
  29. System.out.println("环绕后=="+point.getSignature());
  30. }
  31. }

②xml

  1. <!--注册bean-->
  2. <bean id="userService" class="service.UserServiceImpl"/>
  3. <bean id="myAnnotationAopCut" class="diyaop.MyAnnotationAopCut"/>
  4. <!--声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面-->
  5. <aop:aspectj-autoproxy proxy-target-class="false"/>

③测试类一致,执行结果

image.png