上篇文章中已经讲解完毕spring是怎样来解析我们xml中的aop配置,同时也讲到了在解析过程中,它将会为我们创建几个必要的bean对像,接下来我们就讲解spring是如何来创建我们的代理对象的;
在讲IOC的实现原理时,我们就说过,只有我们在第一次使用某个bean的时候,beanFactory才会为我们来创建bean对象(除非设置了lazy-init为false),代理bean的创建和普通bean的创建过程完全一样,这里不多说,可以去看前面的文章;我们直接将断点打到AbstractAutowireCapableBeanFactory.initializeBean()方法中,这个方法是在bean创建完毕,对它进行一些后续处理时得到调用(后续处理包括调用前处理器,调用配置的init-method方法,调用后处理器) 。 如果你忘记了的话,去看看前面IOC原理解析的文章,那里有详细的解释;
瞧瞧下方两个截图:
我们看到,在上篇文章中说到的AspectJAwareAdvisorAutoProxyCreator类在这里将得到调用机会,同时,此时我们的bean还是AopTargetInterfaceImpl类,这是没有任何问题的;
我们跳进后处理方法中去看看;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//先去缓存中看有没有创建好的代理
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//缓存中没有的话,去包装创建一个代理bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 拿到先前spring为我们创建好的AspectJPointcutAdvisor通知器,
//关于通知器中包含的内容,和我们上篇文章说的一样,可以看下截图
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//去创建一个代理bean
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;
}
我们继续去看创建代理bean的方法;
//创建代理bean的方法
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
//创建一个代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
//是否直接代理这个类,这个类没有实现任何接口
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//我们的bean实现了接口,将进入这里,这个方法将填充proxyFactory的interfaces属性,
//也就是配置好代理工厂即将要代理的接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//将specificInterceptors包装成Advisor,这里没什么好说的,specificInterceptors数组里本身装的就是Advisor的实现类
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
//配置好代理工厂的通知器
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//======>>>重点在这里
return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
//先通过createAopProxy()拿到一个代理对象调用处理程序AopProxy,再交给委托对象去创建代理bean
//AopProxy有两个实现类,CglibAopProxy以及JdkDynamicAopProxy
return createAopProxy().getProxy(classLoader);
}
//得到代理委托对象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//如果bean没有实现接口,就创建一个基于Cglib库实现的CglibAopProxy
//现在明白Spring是怎么来选择到底是使用Cglib还是JDK的proxy来创建代理了吧!就是根据bean有没有实现接口来进行选择的!
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()) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
//否则创建基于JDK自带的Proxy实现的JdkDynamicAopProxy
else {
return new JdkDynamicAopProxy(config);
}
}
//真正得到一个代理bean,这里没什么好说的,就是通过JDK自带的Proxy来实现,不明白的话可以去了解下JDK的动态代理
//至于cglib的代理创建原理,我也未做深入研究,感兴趣的话可以自己去看看源码
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//创建代理bean,它的调用处理程序是this,也就是JdkDynamicAopProxy,因为JdkDynamicAopProxy实现了InvocationHandler接口
//故此,当我们后面在调用代理bean的相关方法时,都将先执行JdkDynamicAopProxy的invoke方法,
//而JdkDynamicAopProxy实例中已经存好了我们的Advisor通知器,为后面的方法增强做好了准备!
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
现在调用堆栈一路返回,最终回到我们先前的调用后处理器代码的地方,我们看下截图:
至此,代理bean已经创建完毕,当我们通过getBean()拿到的对象已经是一个代理对象了;下篇文章我们就来讲解代理bean的调用过程中,增强方法到底是如何做到增强的;
现在,我们来总结一下一个代理bean的创建过程,最后再画一个时序图;
首先,通过AspectJAwareAdvisorAutoProxyCreator这个类的后处理方法,代理bean有了创建入口,接下来将创建一个ProxyFactory并配置好这个ProxyFactory,包括配置要代理的接口,以及一系列通知器,然后根据bean是否有实现接口来创建一个JdkDynamicApoProxy或者ObjenesisCglibAopProxy代理处理器,再通过处理器的getProxy()方法获得一个真正的代理对象,拿到代理对象后,方法一路返回最终回到调用后处理方法的地方,替换掉我们原本创建好的bean;