1、注册AnnotationAwareAspectJAutoProxyCreator
首先要了解Spring解析XML配置文件时,遇到自定义节点是如何解析的。可以参考Spring自定义XML标签解析及其原理分析
当Spring遇到这个标签的时候,它会拿到这个标签的命名空间,发现是http://www.springframework.org/schema/aop,接着打开aop的jar包中会发现一个META-INF目录,在该目录下有一个spring.handlers文件,打开后就会发现如下:
http://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
所以对于aop标签的解析就交给了AopNamespaceHandler去处理。
public class AopNamespaceHandler extends NamespaceHandlerSupport {
...
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
可以看到aspectj-autoproxy这个属性是由AspectJAutoProxyBeanDefinitionParser来处理。
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
...
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
this.extendBeanDefinition(element, parserContext);
return null;
}
...
}
AopNamespaceUtils类
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
//【步骤1】注册或升级AutoProxyCreator定义beanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//【步骤2】对proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//【步骤3】注册组件并通知,便于监听器做进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}
跟踪上面的【步骤1】,如下:
AopConfigUtils类:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
...
if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if(!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if(currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
//新建一个BeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Integer.valueOf(-2147483648));
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
上面目的是往BeanDefinitionRegistry添加一个AnnotationAwareAspectJAutoProxyCreator类的beanDefinition,beanbeanName为org.springframework.aop.config.internalAutoProxyCreator(相关属性可参考AbstractBeanDefinition属性一览)。如果存在同样beanName的beanDefinition,那就根据优先级来决定是否要改变该beanDefinition的beanClassName,其中优先级为(InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator)。
接着上面的【步骤2】会对proxy-target-class以及expose-proxy属性进行处理,如下
AopNamespaceUtils类
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if(sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute("proxy-target-class")).booleanValue();
if(proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute("expose-proxy")).booleanValue();
if(exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
AopConfigUtils类
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
实际就是根据配置改变beanDefinition中的属性。
2、分析AnnotationAwareAspectJAutoProxyCreator
继承图如下:
可以看到该类实现了BeanPostProcessor接口,那它就可以对实例化后的bean进行后置增强;同时它还实现了InstantiationAwareBeanPostProcessor接口,该接口是BeanPostProcessor的其中一个子接口,实现这个接口,可以在Spring实例化bean之前,有机会返回自己的bean实例来中断Spring实例化bean。所以有两个地方有机会给bean进行增强。(可以参考Spring IOC实现原理笔记(三) – 加载bean实例)
看其中eanPostProcessor接口中的postProcessAfterInitialization它是如何实现的
父类AbstractAutoProxyCreator
//bean实例化后
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if(!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//已经处理过
if(beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {//不需要代理
return bean;
}
//给定的bean类是基础设施类(如Advice等)或配置了不需要自动代理就不需要创建代理类
else if(!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//如果存在增强方法则创建代理
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
//如果获取到了增强则需要针对增强创建代理
if(specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建代理
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
- 获取增强器需要遍历在beanFactory中所有注册的bean,找出声明了AspectJ注解的类,然后对其进行增强器的提取,把提取结果加入缓存。
- 获得所有增强器后,就要筛选出使用于当前的bean的增强器。
- 筛选出增强器后,就是创建代理类了。
下面看看如何创建代理类的:
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
//获取当前类中的相关属性
proxyFactory.copyFrom(this);
if(!proxyFactory.isProxyTargetClass()) {
if(this.shouldProxyTargetClass(beanClass, beanName)) {
//使用CGLib代理
proxyFactory.setProxyTargetClass(true);
} else {
//添加接口
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//封装增强器
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
for(Advisor advisor:advisors) {
//加入增强器
proxyFactory.addAdvisor(advisor);
}
//设置要代理的类
proxyFactory.setTargetSource(targetSource);
this.customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if(this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.getProxyClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
...
return this.getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//不优化 & proxy-target-class属性不为true & 实现了接口
if(!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);//JDK代理
} else {
Class<?> targetClass = config.getTargetClass();
...
//如果目标类不是接口,也不是代理类就使用CGLib
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass)?new ObjenesisCglibAopProxy(config):new JdkDynamicAopProxy(config));
}
}
上面把创建代理类的任务交给了ProxyFactory(用法可参考Spring AOP实现原理笔记(一) – 简单介绍),其中返回的代理分JdkDynamicAopProxy和ObjenesisCglibAopProxy.
3. JdkDynamicAopProxy分析
JdkDynamicAopProxy实现了InvocationHandler接口,所以主要逻辑在invoke方法,从上面可以看到是通过其getProxy方法拿到代理实例的,代码如下
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
public Object getProxy(ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
...
Object retVal;
if(!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
//有时候目标对象内部的自我调用将无法实施切面中的增强,则需要通过侧属性暴露代理
if(this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if(target != null) {
targetClass = target.getClass();
}
//获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if(chain.isEmpty()) {
//为空就直接反射调用
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
} else {
//将拦截器封装在ReflectiveMethodInvocation,再用其proceed进行链式调用
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if(retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if(retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
} finally {
if(target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if(setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
...
}
看链式调用增强器部分
ReflectiveMethodInvocation类
public Object proceed() throws Throwable {
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
//动态匹配方法,匹配则执行拦截器,不匹配就不执行
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
//普通拦截器,就直接调用拦截器
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
4.ObjenesisCglibAopProxy分析
class ObjenesisCglibAopProxy extends CglibAopProxy {
...
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
if(objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
} catch (Throwable var7) {
...省略logger
}
}
if(proxyInstance == null) {
try {
proxyInstance = this.constructorArgs != null?proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs):proxyClass.newInstance();
} catch (Throwable var6) {
...省略throw
}
}
((Factory)proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
}
上面没有看到getProxy方法,所以是在其父类中
CglibAopProxy类
public Object getProxy(ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
int x;
if(ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for(Class<?> additionalInterface:additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
//验证Class
this.validateClassIfNecessary(proxySuperClass, classLoader);
//创建及配置Enhancer
Enhancer enhancer = this.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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
//获取拦截器(将advised属性封装成DynamicAdvisedInterceptor等并加入Callback)
Callback[] callbacks = this.getCallbacks(rootClass);
Class<?>[] types = new Class[callbacks.length];
for(x = 0; x < types.length; ++x) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//这里调用了上面子类的方法生成代理类
return this.createProxyClassAndInstance(enhancer, callbacks);
} catch...
}
CGLib用法需要实例化一个Enhancer,然后自定义拦截器加入Callback中,在调用代理时直接激活拦截器中的intercept方法(可参考样例Spring AOP实现原理笔记(一) – 简单介绍)。DynamicAdvisedInterceptor屎其中一种了拦截器,如下:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
...
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
Object var11;
try {
if(this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = this.getTarget();
if(target != null) {
targetClass = target.getClass();
}
//获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
if(chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
//拦截器链为空则直接激活原方法
retVal = methodProxy.invoke(target, args);
} else {
//进链逐个调用
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
}
retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
return retVal;
} finally {
if(target != null) {
this.releaseTarget(target);
}
if(setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
...
}
上面的实现和JDK方式实现代理中的invoke方法大同小异,都是首先构造链,然后封装此链进行串联调用。JDK中直接构造ReflectiveMethodInvocation,而CGLib使用CglibMethodInvocation(CglibMethodInvocation继承ReflectiveMethodInvocation)。
PS:Spring4.0内联了objenesis库,使得使用CGLib代理不再要求目标类提供无参构造函数。
参考
Spring源码(4.2.2.RELEASE)
《Spring源码深度解析》