对Spring中AOP的理解

1)什么是AOP:

        AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),切面将那些与业务无关,却被业务模块共同调用的逻辑提取、并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。

2)AOP代理:

        AOP思想实现的关键在于AOP代理技术,AOP代理主要分为静态代理和动态代理。

        静态代理的代表为AspectJ;动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

3)什么是代理?

        指为一个目标对象提供一个代理对象,并由代理对象控制对目标对象的引用,使用代理对象,是为了在不修改目标对象的基础上,增强目标对象的业务逻辑。

        静态代理的特点是: 为每一个业务Bean的增强都提供一个代理类,由代理类来创建代理对象。

        动态代理的特点是:静态代理会为每一个业务Bean增强都提供一个代理类,由代理类来创建代理对象, 而动态代理并不存在代理类,代理对象是通过动态字节码技术,在程序运行时直接动态生成代理对象( 反射)。

4)AOP中的相关概念

  • Aspect(切面): 将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)。

  • Joint point(连接点):典型的所谓连接点是指那些可能会被增强的点,在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。

  • Pointcut(切入点):所谓切入点是指我们对哪些连接点确定进行增强处理的点,它指的是 Advice 增强处理确定将要发生的地方。

  • Advice(增强):Advice增强指的是在 Pointcut 切入点中具体要做的事情,它一般使用before前置增强、after后置增强、 around环绕增强来区别是在每个切入点之前、之后还是代替执行的代码。

  • Target(目标对象):进行 Advice增强处理 的目标对象。

  • Proxy(代理对象):一个类被 AOP 织入增强处理后,产生的一个代理对象。

  • Weaving(织入):是指把增强处理应用到目标对象,来生成新的代理对象的这么一个过程。Spring的AOP默认采用动态代理织入的方式。

5)动态代理的实现方案:

        AOP的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。所谓的动态代理就是说:动态代理并不存在代理类,再由代理类来创建代理对象,动态代理的代理对象是通过动态字节码技术,在程序运行时直接动态生成代理对象( 反射)。

        jdk代理 :JDK动态代理要求该业务Bean必须要有实现的接口,通过和该业务Bean--即目标对象,实现相同的接口保证功能一致。

        cglib代理 : CGLib动态代理是通过继承该业务Bean--即目标对象,来保证功能一致,即,生成目标对象的子类, 这个子类对象就是代理对象。

6)Spring默认选择:

        Spring会自动选择代理。Spring会自动为我们选择一种动态代理方式,如果目标有接口,Spring会选择JDK的,否则Spring会选择CGLib。

  • Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。

  • SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常,而改为了默认使用 CGLIB

  • 在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxyTargetClass配置已无效。

7)AOP代码示例:

1》创建业务接口:

public interface IPersonService {
      void save(String name);
}

2》创建业务类:

@Service
public class PersonServiceImpl implements IPersonService {
      @Override
      public void save(String name) {
            System.out.println("用户名已保存,用户名为: " + name);
      }
}

3》创建(aop)切面类:

@Aspect
@Component
public class AspectPersonService {

      /**
       * 在这里定义切入点,后面的xx通知直接引用该切入点方法pointCut()即可。
       *
       * PS:在spring中,不管是连接点还是切入点,这些点指的都是方法,因为spring只支持方法类型的连接点。
       */
      @Pointcut(value = "execution(* zyh.example.demo.spring.aop.PersonServiceImpl.save(..))")
      public void pointCut() {
      }

      /**
       * 环绕通知
       */
      /*@Around(value = "pointCut()")
      public void aroundMethod() {
            System.out.println("这里是环绕通知....");
      }*/


      /**
       * 前置通知
       */
      @Before(value = "pointCut()")
      public void beforeMethod()  {
            System.out.println("这里是前置通知...");
      }


      /**
       * 后置通知
       */
      @After(value = "pointCut()")
      public void afterMethod() {
            System.out.println("这里是后置通知...");
      }
}

4》创建测试类:

@SpringBootTest
public class AopTest01 {

      @Autowired
      private IPersonService personService;

      @Test
      public void test1() {
            //执行personService的save()方法:
            personService.save("交控科技");
      }
}

5》查看执行结果:

环绕通知未注释:

对Spring中AOP的理解_第1张图片

 

注释掉环绕通知:

对Spring中AOP的理解_第2张图片

 

你可能感兴趣的:(spring,java)