spring 之AOP源码分析
SpringAOP是基于动态代理来实现的,那么Spring是如何实现对对象的动态代理从而实现AOP的呢,本文我们将对源码进行一个分析。
Spring 代理对象创建流程
1.Spring对象的创建流程在Spring学习笔记中已经有详细的描述,我们直接进入AbstractAutowireCapableBeanFactory#doCreateBean中initializeBean方法。Spring会在applyBeanPostProcessorsAfterInitialization()方法中完成对对象的代理。可以看到此时bean对象还未被代理增强。
2.进入applyBeanPostProcessorsAfterInitialization()方法,该方法会遍历BeanPostProcessors,并调用processor的postProcessAfterInitialization()方法,我们找到AOP相关的 AspectjAwareAdvisorAutoProxyCreator,进入postProcessAfterInitialization()方法。
3.AbstractAutoProxyCreator#postProcessAfterInitialization()方法中,首先查看是否在earlyProxyReferences里存在,若存在也就是已经在处理循环依赖时完成了AOP增强,不存在就考虑是否要代理,进入wrapIfNecessary()方法。
4.wrapIfNecessary()首先会进行判断是否已经完成代理,是否需要代理,是否跳过代理。然后获取所有的Advice转化为拦截器组,并进行代理获得代理对象,装入advisedBeans后返回代理对象。
targetSourcedBeans 存入的时自定义targetSource 完成的代理对象, 自定义TargetSource将会在AbstractAutoProxyCreator#postProcessBeforeInstantiation方法中完成也就是预初始化方法中。
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;
}
// Create proxy if we have advice.
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;
}
至此AOP代理对象创建完成。
动态代理实现细节(CGLIB OR JDK)
1.AbstractAutoProxyCreator#createProxy 真正实现动态代理
如果isProxyTargetClass为false(spring默认设为false),进入shouldProxyTargetClass() ,确定给定的bean是否应该用它的目标类而不是它的接口来代理。evaluateProxyInterfaces()检查给定bean类上的接口,并在有符合条件(reasonable)得接口的情况下将它们应用于代理工厂。条件为(!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && ifc.getMethods().length > 0)排除容器的callback接口,语言内部接口和没有方法的接口。若不满足条件,则设置用目标类来代理。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, 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());
}
/**
* Determine whether the given bean should be proxied with its target class rather than its interfaces.
* <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
* of the corresponding bean definition.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @return whether the given bean should be proxied with its target class
* @see AutoProxyUtils#shouldProxyTargetClass
*/
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
/**
* Check the interfaces on the given bean class and apply them to the {@link ProxyFactory},
* if appropriate.
* <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface}
* to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise.
* @param beanClass the class of the bean
* @param proxyFactory the ProxyFactory for the bean
*/
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
proxyFactory.setProxyTargetClass(true);
}
}
/**
* Determine whether the given interface is just a container callback and
* therefore not to be considered as a reasonable proxy interface.
* <p>If no reasonable proxy interface is found for a given bean, it will get
* proxied with its full target class, assuming that as the user's intention.
* @param ifc the interface to check
* @return whether the given interface is just a container callback
*/
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
/**
* Determine whether the given interface is a well-known internal language interface
* and therefore not to be considered as a reasonable proxy interface.
* <p>If no reasonable proxy interface is found for a given bean, it will get
* proxied with its full target class, assuming that as the user's intention.
* @param ifc the interface to check
* @return whether the given interface is an internal language interface
*/
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
2.经过一系列调用,进入DefaultAopProxyFactory#createAopProxy(),
当满足以下一个条件时,会创建CGLIB代理:
optimize被设为ture- proxyTargetClass被设为ture
- 没有接口被指定(没有合理的接口,通过evaluateProxyInterfaces()判断后)
通常来说,当prxyTargetClass被指定为true时会强制使用CGLIB 代理
当实现了一个reasonable接口时,会使用JDK动态代理。
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);
}
}