SpringAOP底层原理探究

spring 中aop 使用哪种方式的代理?

使用idea 打开spring项目,双加shift,搜索AopProxy,可以找到这个类:
SpringAOP底层原理探究_第1张图片
查看这个类有几个实现类:
SpringAOP底层原理探究_第2张图片

可以看到有三个:

	CglibAopProxy.java
	JdkDynamicAopProxy.java
	ObjenesisCglibAopProxy.java
	
	但是这三个类其实代表的是两种,分别是 jdk的代理类和cglib的代理类

代理类是在什么时候产生的?

下面通过这个测试类探究一下

public class Test {
    public static void main(String[] args) {
        // 初始化 bean
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AopConfiguration.class);
        // context.getBean()的底层就是 map.get()方法 DefaultSingletonBeanRegistry 类下  getSingleton() 方法中
        // 代理对象不是在get的时候代理的,而是在init的时候完成的
        context.getBean(AopService.class).query();
    }
}

在这先说一下结论:

getbean()方法底层就是 map.get()方法,这个map对应的是 concurrentHashMap(),也就是说,getBean()这个方法的代理类其实是从spring 中的 concurrentHashMap() 中得到了(这个map也可以被称为spring容器),说明其实在这个方法的时候,代理类已经产生了,从上面这测试类就可以看出,真正创建代理类的是在初始化的时候.

下面开始通过对context.getbean()方法(获取代理对象的方法)的追踪:
context.getBean(AopService.class);
SpringAOP底层原理探究_第3张图片
AbstractApplicationContext.java中:
SpringAOP底层原理探究_第4张图片
DefaultListableBeanFactory.java中:
在这里插入图片描述
SpringAOP底层原理探究_第5张图片
SpringAOP底层原理探究_第6张图片
SpringAOP底层原理探究_第7张图片
在这里插入图片描述
AbstractBeanFactory.java中
在这里插入图片描述
在这里插入图片描述

DefaultSingletonBeanRegistry.java中:
SpringAOP底层原理探究_第8张图片
在这里插入图片描述
       从上面这流程中可以看出, context.getBean() 方法最终取出的代理类是从 ConcurrentHashMap() 中获取的到,说明此意代理类已经生产并且放在了ConcurrentHashMap()中,这个ConcurrentHashMap()其实就是 String的容器 .所以, 可以推出 代理类是在初始化的时候放到容器中的 .

原生对象在那创建的?

        由上面可以推出,代理类是在初始化的时候就已经放在ConcurrentHashMap()中了,那么是怎么放进去的呢?因为过程中牵扯到的代码太多,我们可以换个思路来考虑:
既然getBean()是从ConcurrentHashMap()中获取的代理类,那么我们可以在放进去的那个位置打断点, 由获取的方法singletonObjects.get(beanName)可以推出获取的方法是singletonObjects.put() ,找到这个方法:
SpringAOP底层原理探究_第9张图片
然后开始重新执行,在debug中可以看到执行的路径:
SpringAOP底层原理探究_第10张图片
所以最终的执行路线是由下面这个流程:
在这里插入图片描述
AnnotationConfigApplicationContext.java中:
在这里插入图片描述
AbstractApplicationContext.java中:
SpringAOP底层原理探究_第11张图片
在这里插入图片描述
SpringAOP底层原理探究_第12张图片
DefaultListableBeanFactory.java
SpringAOP底层原理探究_第13张图片
SpringAOP底层原理探究_第14张图片
AbstractBeanFactory.java中 :
在这里插入图片描述
在产生对象的时候,先从spring容器中获取对象(this.getSingleton(beanName)),如果有,返回,如果没有,调用下面的方法创建一个代理对象
SpringAOP底层原理探究_第15张图片
通过观察出传递过程中的变量可以看出,在执行下面这段代码前还没有产生对象,在调用下面这段代码后就产生了代理对象,所以,是在getSingleton()方法中产生了代理对象
SpringAOP底层原理探究_第16张图片
DefaultSingletonBeanRegistry.java中:
由上面可以知道,spring中原生对象与代理对象的转换是在这个方法中的
在这里插入图片描述
经过一步一步检查,发现在下面这个方法中完成了原生对象转换为代理对象:
SpringAOP底层原理探究_第17张图片
执行到这一步后,按F5,执行到下面这个方法中:

AbstractBeanFactory.java
SpringAOP底层原理探究_第18张图片
执行到 createBean方法,跳转到下面这个方法中:
AbstractAutowireCapableBeanFactory.java
SpringAOP底层原理探究_第19张图片
执行到下面这个方法的时候,发现代理对象是通过下面这个方法得到了,所以,跳转到这个方法里面
SpringAOP底层原理探究_第20张图片
进入这个方法里面,查看原生对象的创建以及怎么转换成代理对象
SpringAOP底层原理探究_第21张图片
在下面这个方法中, 创建的原生对象:

	创建原生对象的方法:
		通过beanfactory创建
		通过有参构造方法创建
		通过无参方法构建

在这里插入图片描述
通过对 createBeanInstance(beanName,mdb,args), 可以一直找下去,最后找到ClassUtils.java这个类中,发现在下面这个方法中创建的原生对象,然后一直往下走,最后发现创建原生对象使用的是 Class.forName(innerClassName,false,clToUse) ;
SpringAOP底层原理探究_第22张图片
SpringAOP底层原理探究_第23张图片

在下面这个方法中,有原生对象转换成代理对象

要注意 populateBean() 这个方法的使用.在这个方法中维护bean的各种依赖
(spring 中 bean的创建时先实例化对象,然后调用populateBean对bean的各种依赖进行维护的)

然后 aop 的代理对象的转化是在
this.initializeBean(beanName, exposedObject, mbd) 这个方法中进行的
在这里插入图片描述
AbstractAutowireCapableBeanFactory.java 中有initializebean() 这个方法
SpringAOP底层原理探究_第24张图片
执行后置处理器处理前的执行方法(下面面这个方法) this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 由原生对象转换成代理对象.

后置处理器 BeanPostProcessors

spring容器中很重要的东西,是spring提供的一个拓展点,能够查收spring的bean的初始化过程,spring容器底层借用后置处理器帮我们完成的代理 (beanPostProcessor.java)
在这个bean 放在 spring容器之前,会执行后置处理器中的两个方法:

this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

创建bean ----------------beanPostProcessor 1…2 -------------------map.put()之间,调用了 beanPostProcessor
后置处理器是一个 list, 用户也可以提供自己的后置处理器,会放在这个list中
SpringAOP底层原理探究_第25张图片
在这个方法内部执行后置处理器的:
在这里插入图片描述
方法执行到这里面, this.getBeanPostProcessors() 这个方法获取所有的后置处理器,其中, 第 5 个是代理的后置处理器, 通过这个后置处理器,把原生对象变成代理对象.这就是后置处理器的工作原理:
(在原生对象放进spring容器之前,把原生对象转换成代理对象,然后把代理对象放进容器内)
SpringAOP底层原理探究_第26张图片
SpringAOP底层原理探究_第27张图片

DefaultSingletonBeanRegistry.java中:
SpringAOP底层原理探究_第28张图片
SpringAOP底层原理探究_第29张图片
spring容器创建对象的时候,是先实例化这个对象,然后调用populateBean方法添加这个对象的各种依赖.设置属性

DefaultSingletonBeanRegistry.java中 getSingleton 方法的一些注释:

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    // 判断传入的参数中 beanName 是否为空
    Assert.notNull(beanName, "Bean name must not be null");
    // 获取spring容器 concurrentHashMap
    Map var3 = this.singletonObjects;
    // 使用同步代码块保证线程安全
    synchronized(this.singletonObjects) {
        // 从spring容器中获取 对应名称的bean,判断是否存在
        Object singletonObject = this.singletonObjects.get(beanName);
        // 还没添加到spring容器中
        if(singletonObject == null) {
            // 判断当前单例是否处于销毁状态,如果是,抛出异常: 当前此工厂的对象销毁状态,不能创建单例bean
            if(this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");  }
            // 判断当前日志是否启用调试
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); }
            // 将bean name 添加到singletonsCruuentlyInCreation这样一个set集合中
            // 表示beanname对应的bean正在创建中  (告诉spring容器这个对象正在创建)
            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            // 如果suppressedExceptions 为空,重新创建一个 set集合
            boolean recordSuppressedExceptions = this.suppressedExceptions == null;
            if(recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet();  }
            try {
                // 在这个方法中 完成  bean 原生对象到代理对象的转变
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } catch (IllegalStateException var16) {
                singletonObject = this.singletonObjects.get(beanName);
                if(singletonObject == null) {
                    throw var16;
                }
            } catch (BeanCreationException var17) {
                BeanCreationException ex = var17;
                if(recordSuppressedExceptions) {
                    Iterator var8 = this.suppressedExceptions.iterator();

                    while(var8.hasNext()) {
                        Exception suppressedException = (Exception)var8.next();
                        ex.addRelatedCause(suppressedException);
                    }  }
 			 throw ex;
            } finally {
                if(recordSuppressedExceptions) {
                    this.suppressedExceptions = null; }
                this.afterSingletonCreation(beanName);  }
 		 if(newSingleton) {
                this.addSingleton(beanName, singletonObject); }  }
        // 返回容器中已经存在的 bean 了
        return singletonObject;  } }

总结

springAop底层是通过 class.forName() 方法创建的原生对象,在创建之前,先从commonClassCache中获取(这个commonClassCache是hashMap),如果没有,在通过上述方法创建,在放进concurrentHashMap之前,通过this.applyBeanPostProcessorsBeforeInitialization(bean, beanName)方法调用后置处理器对这个bean进行处理,由原生对象转换

手写添加后置处理器:

项目目录:

SpringAOP底层原理探究_第30张图片

ann : 自定义注解

MyAnn.java

package com.beikai.springboottestdemo.aspect.ann;

import com.beikai.springboottestdemo.aspect.config.MyBeanPostProcessor;
import org.springframework.context.annotation.Import;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by Beikai.Han on 2019/3/27.
 *  自定义注解
 */
@Import(MyBeanPostProcessor.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnn {
}

aop : 切面代码

AopConfig.java

package com.beikai.springboottestdemo.aspect.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * @ClassName AopConfig
 * @Description TODO
 * @Author Admin
 * @Date 2019/3/26 20:55
 * @Version 1.0
 *  定义的切面
 **/
@Aspect
@Component
public class AopConfig {
    /**
     * 设置切点
     */
    @Pointcut("execution(* com.beikai.springboottestdemo.aspect.service..*.*(..))")
    public void pointcut(){

    }

    /**
     * 在切点之前执行的代码
     */
    @Before("pointcut()")
    public void before(){
        System.out.println("start ---------------");
    }
}

config : 一些配置文件

AopConfiguration.java

package com.beikai.springboottestdemo.aspect.config;

import com.beikai.springboottestdemo.aspect.ann.MyAnn;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName AopConfiguration
 * @Description TODO
 * @Author Admin
 * @Date 2019/3/26 21:04
 * @Version 1.0
 **/
@Configuration
@ComponentScan("com.beikai")
//@EnableAspectJAutoProxy
@MyAnn
public class AopConfiguration {

}

MyBeanPostProcessor.java

package com.beikai.springboottestdemo.aspect.config;

import com.beikai.springboottestdemo.aspect.service.Service;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Proxy;

/**
 * Created by Beikai.Han on 2019/3/27.
 */

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 把 bean 通过反射放进去
        if (beanName.equals("aopService")){
            return Proxy.newProxyInstance(MyBeanPostProcessor.class.getClassLoader(),new Class[]{Service.class},new MyHandler(bean));
        }
        return bean;
    }
}

MyHandler.java

package com.beikai.springboottestdemo.aspect.config;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by Beikai.Han on 2019/3/27.
 */
public class MyHandler implements InvocationHandler {

    private Object object;

    public MyHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("反射执行了");
        return method.invoke(object,args);
    }
}

service : 业务层

AopService.java

package com.beikai.springboottestdemo.aspect.service;

import org.springframework.stereotype.Component;

/**
 * @ClassName AopService
 * @Description TODO
 * @Author Admin
 * @Date 2019/3/26 20:58
 * @Version 1.0
 **/
@Component
public class AopService implements Service {
    public void query(){
        System.out.println("spring ---- init --- ");
    }
}

Service.java
package com.beikai.springboottestdemo.aspect.service;

/**
 * Created by Beikai.Han on 2019/3/27.
 */
public interface Service {
    public void query();
}

** test: 测试启动

Test.java

package com.beikai.springboottestdemo.aspect.test;

import com.beikai.springboottestdemo.aspect.config.AopConfiguration;
import com.beikai.springboottestdemo.aspect.service.AopService;
import com.beikai.springboottestdemo.aspect.service.Service;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCreationNotAllowedException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.Assert;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;

/**
 * @ClassName Test
 * @Description TODO
 * @Author Admin
 * @Date 2019/3/26 21:05
 * @Version 1.0
 * 

* 测试类 **/ public class Test { public static void main(String[] args) { // 初始化 bean AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfiguration.class); // context.getBean()的底层就是 map.get()方法 DefaultSingletonBeanRegistry 类下 getSingleton() 方法中 // 代理对象不是在get的时候代理的,而是在init的时候完成的 context.getBean(Service.class).query(); } }

pom文件


    org.springframework
    spring-aop
    5.1.5.RELEASE



    org.aspectj
    aspectjrt
    1.6.12


    org.aspectj
    aspectjweaver
    1.6.12


    cglib
    cglib
    2.2

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