回顾一下我们说过Spring bean的生命周期主要大概有以下几个步骤:
- 创建bean的实例
- 给实例化出来的bean填充属性
- 初始化bean
- 通过IOC容器使用bean
- 容器关闭时销毁bean
之前我们已经就前两部分做了比较详尽的分析。
本文想要跟大家分享的是Spring中非常重要的概念——AOP。AOP确切发生的步骤是在第三步初始化bean中的某一步,请注意本文还没有把所有bean初始化的步骤说完,但Spring AOP无论在日常工作中,还是在面试中都是比较重要的概念,所以单独给它分析一下。
AOP和Spring AOP
这里需要说明一件事:AOP不是Spring特有的,AOP跟OOP一样,是一种理念,是将纵向的业务流程中的一些水平功能(日志记录等)逻辑单独拎出来做处理,从而减少这些必要但非核心业务逻辑的耦合,增强程序员对业务逻辑的关注。只不过Spring提供了一种AOP的实现,叫做Spring AOP。
同样,IOC也不是Spring特有的,IOC是一种控制反转理念,将对象的初始化交给容器或者说框架本身来做,程序员开始上手只需要拿这个instance就可以了。Spring IOC也只是Spring提供的IOC理念的实现。
Spring AOP的用法以及各种术语(切面、连接点、切点、织入等)不是本文要纠结的重点,如果还不清楚基本用法的建议读到这里可以右上角x掉了。
回顾doCreateBean()
我们在分析bean生命周期的前两步的时候,都走到doCreateBean()这个方法,然后分流了。还记得这个方法大体上分3步吗:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass();
Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { }
try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); }
return exposedObject; }
|
第一步,根据扫描出来的BeanDefinition推断出来的构造方法,然后反射来创建实例。
第二步,根据扫描出来的所有带有@Autowire标签的依赖实例,进行依赖注入。
第三步,bean初始化,我们的AOP功能就在这里实现,除了AOP之外,还有一系列的postProcessor在此被调用,完成各种bean增强。
前面的过程都一样了,我们就从doCreateBean()开始吧。
Spring AOP源码
Spring AOP创建入口
在上面第三步中,我们点进initializeBean()方法(省略了非必要代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }
try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
return wrappedBean; }
|
所以在bean初始化时,大体分为3步:
- 调用init之前的postProcessor;
- 做初始化;
- 调用init之后的postProcessor。
这里只需要了解postProcessor有很多种,包括Spring自身提供的,和程序员对Spring做扩展自己写的。这些postProcessor会存在BeanFactory的一个COW的List里面,你可以自定义一个postProcessor,并且重写它的postProcessBeforeInitialization()和postProcessAfterInitialization()方法来对Spring进行扩展。
Spring AOP发生在第3步,也就是bean完成了初始化之后调用的postProcessor。
applyBeanPostProcessorsAfterInitialization()
这个方法是抽象BeanFactory中提供的方法,主要就是拿到所有的postProcessor,并且迭代调用它的postProcessAfterInitialization()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
|
Spring AOP使用的postProcessor是AbstractAutoProxyCreator提供的,从它的Class定义也可以看出来它是一个postProcessor(implements):
1 2
| public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
|
所以这个AbstractAutoProxyCreator重写的postProcessAfterInitialization()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
|
wrapIfNecessary()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return 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; }
this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
|
所以这里主要有2步:
- 拿到所有的advice通知 - getAdvicesAndAdvisorsForBean();
- 根据拿到的advice通知方法,createProxy()创建代理进行bean的AOP增强。
getAdvicesAndAdvisorsForBean()
1 2 3 4 5 6 7 8 9 10 11
| @Override @Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
|
这里需要说一下Advisor是怎么工作的,为啥有的advice就能做前置增强,有的就可以做后置,而有的可以做环绕增强呢?
首先说Advisor有非常多的子类实现,每个子类都封装了一个Advice的成员变量;这个Advice是一个接口,也有非常多的实现类,我们就拿AspectJAfterAdvice这个Advice的实现类来举例吧,它是AspectJ风格的后置增强实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { @Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } }
}
|
它在重写的invoke()方法时,先去做proceed()调用Invocation对象自身定义的method(),然后在finally中实现的advice后置增强,代码的执行顺序也是保证了finally块中一定在proceed()执行完(无论是否正常退出)之后进行后置advice。
所以实际上我们在给Spring AOP准备Advisor数组时,做好封装并且拿到数组,然后传给下面创建的代理就可以实现各种增强了。
createProxy()
我们在各种地方都可以看到这么一段话:Spring AOP咋实现的?答通过代理。有几种代理方法?答jdk动态代理和cglib代理。这几乎是地球人都知道的一个层面,那它在源码上是如何体现的?
1 2 3 4 5 6
| protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory();
return proxyFactory.getProxy(getProxyClassLoader()); }
|
省略了不必要的代码之后,它就做了2件事:
- 创建了一个proxyFactory;
- 通过这个proxyFactory去拿代理(创建代理对象)。
中间还有几个简单的调用,我们可以直接来到最下面一层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
|
看吧,经典的2种代理就是在这里体现的。
创建AOP代理后返回的实例
我这里做实验搞了一个最简单的增强bean,它是普通的类(不是接口),开debug模式可以看到,在createProxy()之后,Spring给我返回的是这么一个类:
放大看看:
后面给我加了$$EnhancerBySpringCGLIB$$xxxxx
,事实上,在Context完成初始化之后,我拿到的bean也是这么一个东西:
总结
本文只是把bean初始化中的AOP部分分析了一遍,这个过程中还有其他的一些步骤,主要是各个postProcessor来完成的,所以读者可以从几方面扩展一下:
- 其他的postProcessor和哪些Spring其他的功能相关联,可以自行debug看一下源码;
- 能不能对Spring做一些扩展,也就是自己写一个postProcessor呢?
- 自己写的postProcessor在哪一步被装载进Spring,又在哪里执行的?