前言
有一点Spring基础的同学应该都知道,Spring的动态代理默认使用的是JDK动态代理(对于非接口的类,用cglib,与JDK动态代理类似,这里不多做解释),不清楚JDK动态代理的点这里。并且,我们知道通过jdk动态代理,我们可以拿到一个代理后的对象,而Spring的bean实例化过程,就涉及到代理对象的替换
Spring Bean的生命周期
想知道Spring是如何实现的动态代理,必须对bean的生命周期和实例化过程有初步了解。笔者通过阅读源码,得知一个bean的实例化过程,是由一系列的BeanPostProcessor(后置处理器)处理的,在bean实例化之前的注解解析,实例化过程中确定构造器,实例化后的属性注入,属性注入完的初始化步骤,分别由特定的后置处理器来完成。
如果要在Spring当中实现aop动态代理,笔者认为主要有两种思路:
- 1、实例化之前将BeanDefinition中的class替换为代理类,可以通过自定义BeanFactoryPostProcessor或者ImportBeanDefinitionRegisterar来实现
- 2、实例化完成之后,通过自定义的BeanPostProcessor将对象替换成代理对象
由于jdk动态代理和cglib动态代理,都只提供了获取代理对象的方法,因此我们可以猜测Spring是利用第二种方式实现的。
猜想验证
下面是一段aop切面的demo:
@Aspect
@Component
public class MyAspect {
@Autowired
private MyService myService;
@Pointcut("execution(* com.lwl.controller.MyController.testAop(..))")
public void testAop(){}
@Around("testAop()")
public Object aopWeaveing(ProceedingJoinPoint joinPoint) throws Throwable {
//代理代码,忽略
}
}
下面是被代理的方法和类:
@RestController
@RequestMapping("/aop")
public class MyController {
@GetMapping("test")
@AssertLogin
public String testAop(){
//业务代码,忽略
}
}
bean的实例化过程主要发生在context的refresh方法中的finishBeanFactoryInitialization方法,其中
调用了DefaultLisableBeanFactory的preInstantiateSingletons,通过getBean(beanName)来实例化bean
因此我们跟踪到执行了自定义beanPostProcessor的AbstractAutowireCapableBeanFactory的initializeBean方法当中:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//忽略不重要的代码
//wrappedBean即bean对象
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用beanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用bean中实现的afterPropertiesSet或被@PostConstuct注解修饰的方法,即初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用beanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这里需要明确的是,beanPostProcessor的两个方法postProcessBeforeInitialization和postProcessAfterInitialization都能够替换对象,区别在于postProcessBeforeInitialization在bean执行初始化方法之前执行,简单思考一下,我们对对象进行代理时,很可能需要用到该bean对象初始化之后的属性,因此我们猜测代理的过程发生在初始化之后的postProcessAfterInitialization过程中。
笔者将断点打在调用applyBeanPostProcessorsAfterInitialization方法之前,可以看到此时的wrapperBean还是MyController
断点往下走,执行完applyBeanPostProcessorsAfterInitialization方法,发现wrappedBean已经变成了CGLib动态代理对象:
这就验证了我们之前的猜测
实现原理分析
我们进入applyBeanPostProcessorsAfterInitialization方法看看spring到底做了什么事
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历容器中所有的beanPostProcessor,执行postProcessAfterInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到该方法中遍历了spring容器里所有的beanPostProcessor,并挨个执行postProcessAfterInitialization。由于笔者是在平时开发的springboot环境中随便写了一个aop类做调试,因此此时的容器中有非常多的后置处理器,简单看一下一共有三十个:
目前我们能确定的是,一定是某一个后置处理器执行完了postProcessAfterInitialization方法,才将对象替换成了代理对象,那如何从这么多的beanPostProcessor中找到那个凶手?两种方法:
- 1、还是用之前打断点的方法,看看哪一个后置处理器执行完以后对象发生了改变,但是这里有三十多个后置处理器,作为一个有追求的程序员考虑到算法时间复杂度为O(n),不行这个方法需要优化
-
2、靠猜- -笔者死磕源码的经历,大部分情况靠猜,事实上百分之八十都能猜对。这三十个beanPostProcessor中,从名字上看,似乎只有数组下标为5的AnnotationAwareAspectJAutoProxyCreator看起来比较可疑(又是Aspect又是AutoProxy的)
因此我们将断点条件修改为只有beanPostProcessor为该对象时才暂停:
继续调试,成功进入断点,执行之前为MyController
断点执行完以后对象变成了Cglib代理对象:
猜想再次被验证了,那么我们的重点就转换为查看这个beanPostProcessor中究竟做了什么,一路跟踪:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//重点看这个方法,它返回了代理后的对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//根据bean的类型和bean的名称,获取与该类相关的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//此处创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return bean;
}
protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//从切面对象中提取我们定义的增强逻辑代码,构造成proxyFactory代理工厂
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//通过代理工厂创建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
//该方法为proxyFactory中的getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
调试发现createAopProxy()返回了一个CglibAopProxy,说明此时使用的是cglib动态代理
而CglibAopProxy的getProxy里面就是我们非常熟悉的cglib动态代理的代码了:
public Object getProxy(@Nullable ClassLoader classLoader) {
//rootClass即MyController.class
Class> rootClass = this.advised.getTargetClass();
Class> proxySuperClass = rootClass;
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//根据要代理的类生成callback,这个是重点
Callback[] callbacks = getCallbacks(rootClass);
Class>[] types = new Class>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
return createProxyClassAndInstance(enhancer, callbacks);
}
private Callback[] getCallbacks(Class> rootClass) throws Exception {
//advised即之前创建好的proxyFactory,包含了我们交给spring管理的所有Aspect
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
//将切面构造成Callback,主要看这个类
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
... ...
}
//构造的callback:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//重点看重写的intercept方法
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
//如果代理对象被设置为可以暴露,则将当前的代理对象注入
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
//把切面的增强逻辑转换成list
List
总结
Spring的aop,是在bean被实例化并初始化之后,通过beanPostProcessor的postProcessAfterInitialization,通过cglib(jdk动态代理),在实际逻辑执行前后插入我们的增强逻辑