在上一篇文章中,已经分析了当前匹配目标类的增强器的获取。
在wrapIfNecessary()方法中若获取的增强器不为空,则为之创建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// 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;
}
代理的创建委托给了ProxyFactory
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// 获取当前类中的相关属性,比如proxyTargetClass,exposeProxy.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
//获取目标类所实现的接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
//封装Advisor到proxyFactory,其中涉及拦截器、增强方法的封装
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
...
return proxyFactory.getProxy(this.proxyClassLoader);
}
由于Spring还涉及了拦截器(实现了MethodIntecptor接口)、增强方法等方式来对逻辑进行增强,因此此处统一封装成Advisor类型进行统一处理
接下来就是代理的创建了,如刚刚所说,代理的创建委托给了ProxyFactory
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
跟踪下去,可以看见Spring可以通过两种方式创建代理,一种是JDK动态代理,另外一种是CGLIB代理
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()) {
return new JdkDynamicAopProxy(config);
}
//CGLIB代理
return CglibProxyFactory.createCglibProxy(config);
}
else {
//JDK动态代理
return new JdkDynamicAopProxy(config);
}
}
Spring是如何选择的呢?
从If判断条件可以看到:optimize,proxyTargetClass,hasNoUserSuppliedProxyInterfaces能影响spring的选择方式
optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,可能我们对这个属性不怎么了解。
proxyTargetClass这个就是我们在分析<aop:aspectj-autoproxy>,若指定了proxy-target-class属性为true,则使用CGLIB代理
<aop:aspectj-autoproxy proxy-target-class="true"/>
hasNoUserSuppliedProxyInterfaces是否存在代理接口
一般来说,现在基本就是面向接口编程,所以一般service层均实现了接口,spring默认情况会使用JDK动态代理。
先看看CglibProxyFactory.getProxy()方法
public Object getProxy(ClassLoader classLoader) {
...
try {
Class<?> rootClass = this.advised.getTargetClass();
...
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
...
//设置代理目标类
enhancer.setSuperclass(proxySuperClass);
...
Callback[] callbacks = getCallbacks(rootClass);
...
//设置callback
enhancer.setCallbacks(callbacks);
// 创建代理
Object proxy;
if (this.constructorArgs != null) {
proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
}
else {
proxy = enhancer.create();
}
return proxy;
}
...
}
上面的代码即是使用CGLIB代理的一般步骤:
1、创建Enhancer
2、设置代理目标类
3、设置callback,其中返回的callback均是DynamicAdvisedInterceptor类型,明显该类实现了MethodInterceptor,当调用目标类的方法时,就会调用intercept()方法
4、创建代理
因此此时getBean(beanName)返回的就是一个代理了。
当我们获取bean并调用其方法时
Object object = applicationContext.getBean("xxx");
object.someMethod();
此时就会调用到DynamicAdvisedInterceptor,intercept()方法
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
...
try {
//expose-proxy属性使得对于目标对象内部的自我调用也能增强
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
...
//获取拦截器链
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 CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
当然最重要的莫过于获取拦截器链,spring获取拦截器链的大致做法是把该增强器里的各种通知增强到方法中,比如若存在@After通知,则把相应的AspectJAfterAdvice加入进拦截器链等。
然后就调用CglibMethodInvocation.proceed();
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//获取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//动态调用?
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
//一般我们通过注解配置的就属于普通拦截器
else {
//普通拦截器,直接调用
//MethodBeforeAdviceInterceptor对应@Before
//AspectJAroundAdvice对应@Around
//AspectJAfterAdvice对应@After
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
currentInterceptorIndex初始值为-1,当拦截器链都执行完了,if判断条件成立即会调用目标方法。
invoke()方法将this作为参数传递保证了递归调用。
比如在MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {
...
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
执行完了@Before方法之后,又会调用proceed()方法,形成递归调用,从代码中也可以看到@Before通知是在目标方法之前调用
@After通知
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}
同理,也可以看到@After通知是在目标方法执行完之后执行。
这些通知在执行各自的方法都会调用AbstractAspectJAdvice中的invokeAdviceMethod方法,当然spring同样是通过反射能到方法调用的
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
throws Throwable {
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
...
try {
//利用反射调用方法
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
..
}
@Around通知就稍微有点复杂
@Around通知
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor {
...
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
如上分析,当调用到方法标有@Around时
@Around("test()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around-begin");
Object object = pjp.proceed();
System.out.println("around-end");
return object;
}
pjp.proceed()会克隆MethodInvocation在调用proceed()方法继续执行拦截器链
public Object proceed() throws Throwable {
return this.methodInvocation.invocableClone().proceed();
}
因为是递归调用,所以当执行完目标方法之后就程序就会回到around方法中,执行后续操作。
对于JDK动态代理,只是在初始化的时候不一样,其他基本同CGLIB代理类似,这里不做分析。
以上基本就是AOP的基本原理了。