使用idea 打开spring项目,双加shift,搜索AopProxy,可以找到这个类:
查看这个类有几个实现类:
可以看到有三个:
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);
AbstractApplicationContext.java中:
DefaultListableBeanFactory.java中:
AbstractBeanFactory.java中
DefaultSingletonBeanRegistry.java中:
从上面这流程中可以看出, context.getBean() 方法最终取出的代理类是从 ConcurrentHashMap() 中获取的到,说明此意代理类已经生产并且放在了ConcurrentHashMap()中,这个ConcurrentHashMap()其实就是 String的容器 .所以, 可以推出 代理类是在初始化的时候放到容器中的 .
由上面可以推出,代理类是在初始化的时候就已经放在ConcurrentHashMap()中了,那么是怎么放进去的呢?因为过程中牵扯到的代码太多,我们可以换个思路来考虑:
既然getBean()是从ConcurrentHashMap()中获取的代理类,那么我们可以在放进去的那个位置打断点, 由获取的方法singletonObjects.get(beanName)可以推出获取的方法是singletonObjects.put() ,找到这个方法:
然后开始重新执行,在debug中可以看到执行的路径:
所以最终的执行路线是由下面这个流程:
AnnotationConfigApplicationContext.java中:
AbstractApplicationContext.java中:
DefaultListableBeanFactory.java
AbstractBeanFactory.java中 :
在产生对象的时候,先从spring容器中获取对象(this.getSingleton(beanName)),如果有,返回,如果没有,调用下面的方法创建一个代理对象
通过观察出传递过程中的变量可以看出,在执行下面这段代码前还没有产生对象,在调用下面这段代码后就产生了代理对象,所以,是在getSingleton()方法中产生了代理对象
DefaultSingletonBeanRegistry.java中:
由上面可以知道,spring中原生对象与代理对象的转换是在这个方法中的
经过一步一步检查,发现在下面这个方法中完成了原生对象转换为代理对象:
执行到这一步后,按F5,执行到下面这个方法中:
AbstractBeanFactory.java
执行到 createBean方法,跳转到下面这个方法中:
AbstractAutowireCapableBeanFactory.java
执行到下面这个方法的时候,发现代理对象是通过下面这个方法得到了,所以,跳转到这个方法里面
进入这个方法里面,查看原生对象的创建以及怎么转换成代理对象
在下面这个方法中, 创建的原生对象:
创建原生对象的方法:
通过beanfactory创建
通过有参构造方法创建
通过无参方法构建
通过对 createBeanInstance(beanName,mdb,args), 可以一直找下去,最后找到ClassUtils.java这个类中,发现在下面这个方法中创建的原生对象,然后一直往下走,最后发现创建原生对象使用的是 Class.forName(innerClassName,false,clToUse) ;
要注意 populateBean() 这个方法的使用.在这个方法中维护bean的各种依赖
(spring 中 bean的创建时先实例化对象,然后调用populateBean对bean的各种依赖进行维护的)
然后 aop 的代理对象的转化是在
this.initializeBean(beanName, exposedObject, mbd) 这个方法中进行的
AbstractAutowireCapableBeanFactory.java 中有initializebean() 这个方法
执行后置处理器处理前的执行方法(下面面这个方法) 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中
在这个方法内部执行后置处理器的:
方法执行到这里面, this.getBeanPostProcessors() 这个方法获取所有的后置处理器,其中, 第 5 个是代理的后置处理器, 通过这个后置处理器,把原生对象变成代理对象.这就是后置处理器的工作原理:
(在原生对象放进spring容器之前,把原生对象转换成代理对象,然后把代理对象放进容器内)
DefaultSingletonBeanRegistry.java中:
spring容器创建对象的时候,是先实例化这个对象,然后调用populateBean方法添加这个对象的各种依赖.设置属性
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进行处理,由原生对象转换
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 {
}
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 ---------------");
}
}
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);
}
}
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.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();
}
}
org.springframework
spring-aop
5.1.5.RELEASE
org.aspectj
aspectjrt
1.6.12
org.aspectj
aspectjweaver
1.6.12
cglib
cglib
2.2