当前位置:   article > 正文

Spring框架的AOP实现原理_spring aop实现原理

spring aop实现原理

一、AOP的基本概念

AOP先是一种思想,后是一种技术。

        AOP:面向切面编程,是将那些与业务无关(比如有事务处理,日志管理,权限控制等),但要为业务模块共同调用的逻辑封装成一个可重用的模块,这个模块被称为切面,便于减少系统的重复代码,降低模块间的耦合度,有利于未来的可拓展性和可维护性。如下图所示:

 

        Target:所谓target就是横切新代码的对象

        Joinpoint:连接点,就是在Target上具体的执行点,与Pointcut匹配

        Aspect:切面,其中包装着Advice和Pointcut,是通过Bean注册的基本单位

        Pointcut:切入点,与Joinpoint对应,定义了切面逻辑的执行地点

        Advice:是具体的切入逻辑,切面完成的工作包含在Advice中

        Weaving:织入,把切面加入到对象中,并创建出代理对象的过程

织入时期:(如下表所示)

时期理解
编译期切面在目标类编译时被织入,需要特殊的编译器,Aspect的织入编译器以这种方式织入切面
类加载期切面在目标类加载到JVM时被织入,这种方式需要特殊的类加载器(ClassLoader),可以在目标类引入应用之前增强目标类的字节码
运行期切面在应用的某个时期被织入,在织入切面时,AOP容器会为目标对象动态创建一个代理对象

AOP的通知类型:

        1.前置通知:实现MethodBeforeAdvice接口,在目标方法调用前,执行通知。

        2.环绕通知:实现MethodInterceptor接口,是一个包围目标方法的通知。此通知可以在方法调用前后完成自定义的行为。

        3.后置通知:实现AfterReturningAdvice接口,在目标方法调用后,执行通知,如果方法跑出来异常,那么不执行通知。

        4.异常通知:实现ThrowsAdvice接口,在方法抛出异常的时候,执行通知。

二、Spring的AOP基于动态代理实现

       1. 首先,如果被代理的对象,已经实现了某个接口,那么AOP会使用反射,通过接口的方式来创建代理对象。jdk实现动态代理需要两个组件,一个为InvocationHandler接口,需要编写一个类去实现这个接口,然后重写invoke()方法;

另一个为Proxy类,我们可以通过这个类的newProxyInstance()方法,返回一个代理对象,生成的代理类实现了原来类的所有接口,然后对这些接口进行代理,通过代理对象调用这些方法,底层通过反射来调用我们实现的invoke()方法。

       2. 如果被代理的对象没有实现某个接口,无法通过反射去进行动态代理,这个时候AOP要使用Cglib,基于继承的方式生成一个被代理对象的子类来作为代理。也就是说Cglib要实现一个MethodInteceptor,方法调用会被转发到该类的intercept()方法,然后在需要使用目标对象的时候,通过Cglib动态代理来获取代理对象。

三、两种动态代理的区别

        jdk方式:采用反射的方式,只能对实现接口的类生成代理,加载速度快,执行效率低。

        Cglib方式:通过字节码形式实现,针对类实现代理,加载速度满,但执行效率高。

四、AOP的作用

AOP采用横向抽取机制,取代了传统纵向继承机制的重复性代码,应用主要体现在事务处理,日志管理,权限控制,异常处理等方面。

主要作用:分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。

总结的来说就是AOP主要是保证开发者在不修改源代码的前提下,为系统中的业务逻辑组件添加某种通用功能。

五、代码实现

  1. @Aspect // 面向切面
  2. @Component // UserAOP 注解为Bean
  3. public class UserAOP {
  4. @Pointcut("execution(* com.yjy.service.impl.*.*(..))")
  5. public void pointcut() {
  6. }
  7. @Before("pointcut()")
  8. public void beforeAdvice(JoinPoint point) {
  9. System.out.println("前置增强:" + point.getSignature().getName() + "方法。");
  10. }
  11. @AfterReturning(value = "pointcut()", returning = "obj")
  12. public Object afterReturnAdvice(Object obj) throws Throwable {
  13. // 被增强方法的返回结果
  14. System.out.println("基于Spring AOP的后置返回增强处理.....结果:" + obj);
  15. return obj;
  16. }
  17. @After("pointcut()")
  18. public void afterAdvice(JoinPoint point) {
  19. System.out.println("基于Spring AOP的最终增强处理.....方法:" + point.getSignature().getName());
  20. }
  21. @Around("pointcut()")
  22. public Object aoundAdvice(ProceedingJoinPoint jp) {
  23. System.out.println("环绕增强:" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法,参数:" + Arrays.toString(jp.getArgs()));
  24. Object res = null;
  25. try {
  26. res = jp.proceed();//调用目标方法 返回目标方法的返回结果
  27. } catch (Throwable e) {
  28. System.out.println("环绕增强 catch:" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法,参数:" + Arrays.toString(jp.getArgs()) + "发生异常:" + e.getMessage());
  29. } finally {
  30. System.out.println("基于Spring AOP的环绕增强中finally处理.....");
  31. }
  32. return res;
  33. }
  34. @AfterThrowing(value = "pointcut()", throwing = "e")
  35. public void afterThrowAdvice(JoinPoint p, RuntimeException e) {
  36. // System.out.println("基于Spring AOP的异常返回增强处理.....");
  37. System.out.println("异常增强:" + p.getSignature().getName() + "发生了异常" + e.getMessage());
  38. }
  39. }

  1. ​​​​public interface UserService {
  2. void queryAll();
  3. int addUser();
  4. }
  1. @Service("userServiceImpl")
  2. public class UserServiceImpl implements UserService {
  3. @Override
  4. public void queryAll() {
  5. System.out.println("执行了查询所有的业务");
  6. // 抛出异常
  7. // throw new RuntimeException("没事..测试");
  8. }
  9. @Override
  10. public int addUser() {
  11. System.out.println("执行了 新增");
  12. // if (true) {
  13. // throw new RuntimeException("没事..测试");
  14. // }
  15. return 1;
  16. }
  17. }
  1. public class TestAop {
  2. @Test
  3. public void TestAop() {
  4. ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
  5. UserService userService = (UserService) ac.getBean("userServiceImpl");
  6. userService.addUser();
  7. }
  8. }

运行结果:

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/647791
推荐阅读
相关标签
  

闽ICP备14008679号