• Spring中AOP的实现


    1、概述

    它最大的作用是什么?

    在不更改源代码的情况下,对其原有功能进行增强。使得代码的重用率、开发效率、维护产生极大的方便。

    运用场景

    最常见的有:事务、日志、请求拦截等

    2、使用

    如何在Spring中使用AOP?

    1、开启配置

    @EnableAspectJAutoProxy
    

    2、写代理类和被代理的类

    @Component
    @Aspect
    public class AopConfig {
    
    	@PostConstruct
    	public void init(){
    		System.out.println();
    	}
    
    	@Pointcut("execution(* com.dh.aop.package1.Demo1.*(..))")
    	public void pointCut(){}
    
    	@Before("pointCut()")
    	public void before(){
    		System.out.println("before running... ");
    	}
    }
    
    @Component
    public class Demo1 {
    	
    	public void testAop(){
    		System.out.println("com.dh.aop.package1.Demo1.test1 running...");
    	}
    
    }
    

    当我们从容器中拿出Demo1调用testAop的时候,打印如下:

    before running... 
    com.dh.aop.package1.Demo1.test1 running...
    

    这就是现象,

    3、原理

    本文不讲应用,讲的是AOP在Spring实现的位置,具体实现的逻辑代码下一篇说。

    首先我们看从Spring容器中拿到的Demo1的对象:

    这里很明显,我们的Demo1并不是我们自己写的Demo1了,而是被代理后的Demo1,此代理为Cglib代理,且在我们的类中加入了几个变量,这个变量不是重点,是cglib做一些回调的扩展。

    那么到这里我们就能知道,Spring使用Cglib对我们的原始类进行代理,那么Spring是在哪里对我们的类进行代理的呢?

    首先我们要知道,Spring的执行流程如下:

    这个图是Spring的执行流程,我们这里要找的方法在refresh的registerBeanPostProcessors和finishBeanFactoryInitialization方法。

    registerBeanPostProcessors()

    注册BeanPostProcessor后置处理器,这里的BeanPostProcessor是Spring的后置处理器,可用与我们的Bean实例化以后,对我们的Bean进行改变的类,例如下:

    public class TestMyProxyBeanPostProcess implements BeanPostProcessor {
    
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		if (bean instanceof Demo1){
    			/** 代理Demo1这个类 */
    			bean = 代理的类
    		}
    		return bean;
    	}
    
    	@Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if (bean instanceof Pojo1){
    		}
    		return bean;
    	}
    }
    

    这里可以直接将bean的值更改,并且return回去当做新的bean。

    在我们Spring当中,AOP功能就是使用BeanPostProcessor来实现的。此BeanPostProcessor的名字为:AnnotationAwareAspectJAutoProxyCreator。

    加入此后置处理器的配置其实就是因为我们的@EnableAspectJAutoProxy,此注解中拥有一个@Import(AspectJAutoProxyRegistrar.class)注解,此AspectJAutoProxyRegistrar中执行回调时有一行代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);就是加入此后置处理器的。

    finishBeanFactoryInitialization()

    我们Spring当中所有的单例Bean都是在此方法中进行初始化的(我们这里不讲Bean初始化,只讲AOP的实现位置),我们定位代码到:

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

    可以看到我们的Demo1已经实例化出来了:

    且此时是原始的对象,并没有实例化,那么我们再往下面走:

    注意看,此initializeBean方法执行完的返回值Object就是Demo1的代理类,且为Cglib代理,那么就说明实现AOP代理的方法就这个org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)方法,进入这个方法看看:

    注意此时bean还是原始对象,而不是代理对象,我们F6走下一步后:

    我们的bean变成了代理对象,那么说明重要的代码就在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization方法当中去:

    这里要遍历getBeanPostProcessor拿到的BeanPostProcessor的postProcessAfterInitialization方法,并将返回值赋值给当前的bean,相当于是更改了Bean。我们来看看getBeanPostProcessor这个方法的返回值有哪些BeanPostProcessor:

    我们看这里的这个第3个元素的PostProcessor,此就是我们前面@EnableAspectJAutoProxy注解加入的BeanPostProcessor,我们进入这个循环,看看当这个Processor执行完后是否bean就变成了代理对象。

    当前是循环到我们的AnnotationAwareAspectJAutoProxyCreator了,且当前bean仍然是原始类,现在我们F6走一步:

    看我们的Bean已经变成了代理类,那么我们这里就明白了实现代理AOP的位置了,下面我们简单的看看AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization方法,看看它咋做的。

    更重点的就是org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization此方法的wrapIfNecessary方法:

    这个方法的代码里面怎么实现的AOP,我们下次再聊

  • 相关阅读:
    linux设备驱动第五篇:驱动中的并发与竟态
    chromium浏览器开发系列第二篇:如何编译最新chromium源码
    你所不知道的html5与html中的那些事(二)
    vim 高级使用技巧第二篇
    FFMPEG高级编程第一篇:环境搭建及编译
    android apk 防止反编译技术第一篇-加壳技术
    你所不知道的html5与html中的那些事(一)
    交通视频
    Git命令----放弃本地修改使用服务器上的代码
    IE10(去掉文本框的X)
  • 原文地址:https://www.cnblogs.com/daihang2366/p/15236734.html
Copyright © 2020-2023  润新知