前置了解
关于AOP 我们先看一下一些定义, 我吧AOP的定义给简化了
advice : 代理逻辑,代理建议
pointCut : 切点,代理应用到哪地方
advisor = Advice + pointCut ()
AOP代理例子
接下来我们看一下Spring怎么代理的,比较AOP实际使用的还是代理,写一个Spring代理的例子
首先
被代理类:
public class MyService implements MyInterface{
public User test() {
System.out.println("===");
return new User("xxx");
}
}
代理代码
public class ProxyFactoryTest {
public static void main(String[] args) {
MyService myService = new MyService (); //原始对象
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(myService ); // 原始对象
// 如果原始对象有接口的话
// proxyFactory.setInterfaces(LubanInterface.class);
// 代理逻辑
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// method表示当前执行的方法,args表示执行方法的参数,target表示target对象
System.out.println("执行目标方法调用之前的逻辑");
}
});
MyService proxy = (MyService ) proxyFactory.getProxy(); // 代理对象
proxy.test(); // 代理对象
System.out.println(proxy);
}
}
这里我们看一下这个ProxyFactory的代码
1、存放Advice
org.springframework.aop.framework.AdvisedSupport#addAdvice(org.aopalliance.aop.Advice)
org.springframework.aop.framework.AdvisedSupport#addAdvice(int, org.aopalliance.aop.Advice)
这里需要注意一下,吧Advice封装成了Advisor
org.springframework.aop.framework.AdvisedSupport#addAdvisor(int, org.springframework.aop.Advisor)
org.springframework.aop.framework.AdvisedSupport#addAdvisorInternal
这里就是把Advice 封装成advisor 然后存起来
2、生成代理对象
这里我们再看一下这个ProxyFactory 怎么生成代理对象的,一般生成代理对象一种是JDK自带的,一种是cglib
这里我们看一下Spring的这个ProxyFactory是怎么抉择的
org.springframework.aop.framework.ProxyFactory#getProxy()
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
这里我们先看一下getAopProxyFactory()方法
org.springframework.aop.framework.ProxyCreatorSupport#getAopProxyFactory
org.springframework.aop.framework.ProxyCreatorSupport#ProxyCreatorSupport()
这里我们需要看一下UML的继承图,这里ProxyCreatorSupport是ProxyFactory的父类
所以在创建ProxyFactory的时候就会调用到ProxyCreatorSupport的构造方法
刚刚看完了getAopProxyFactory()方法现在我们来看一下抉择的方法
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
这里就是区分使用JDK代理还是使用CGLIb代理
3、获取代理对象
org.springframework.aop.framework.ProxyFactory#getProxy()
这里我们看getProxy()方法
org.springframework.aop.framework.AopProxy#getProxy()
这里我们看JDK代理
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy()
这里我们分俩段看
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
1、获取需要生成代理对象所需要实现的接口
2、判断接口是否有一些方法
3、代理(这里的代理,我们直接看代理逻辑)
1、获取需要生成代理对象所需要实现的接口
这里注意,除了使用我们存放的代理接口,还加了SpringProxy,Advised,DecoratingProxy 三个接口
3、代理(这里的代理,我们直接看代理逻辑)
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
注意这里的this,这里的this,就是JDKDynamicAopProxy,所以我们直接看这个JDKDynamicAopProxy的invoke方法
org.springframework.aop.framework.JdkDynamicAopProxy
代理逻辑
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// this.advised == proxyFactory
// 这里获取目标对象
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// advised就是ProxyFactory
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget(); // targetSource分为两种:SingletonTargetSource、EmptyTargetSource
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 根据当前方法获取对应的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
// 这里会把要执行的方法给封装一层 为执行对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 执行代理逻辑
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
这里我们先看获取调用拦截器链
org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
注意这里的this,实际上是ProxyFatcory
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
这里实际上就是获取Advisor 里的Pointcut来进行判断,由于我们使用的是DefaultPointcutAdvisor,这个advisor里设置的是TruePointcut,所有的判断都是设置了true
org.springframework.aop.TruePointcut
这里我们在细看一个判断
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
这里匹配成功以后会从Spring里获取一个Interceptors,并吧advisor传递进去
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors
这里会判断advisor是否是MethodInterceptor,如果是那么就直接添加进去,那么如果不是,就会判断是否是this.adapters适配器所能够适配的类型
如果是能够适配的话就使用适配器,这里的适配器是下面这三个
我们在proxyFactory里添加的advice是MethodBeforeAdvice,正好是满足MethodBeforeAdviceAdapter适配的
最后我们再看一下执行
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
在执行方法之前,会把找到的拦截器,代理对象,目标对象,方法,参数都给封装成一个Invocation
然后调用
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
1、这里有一个递归逻辑
注意 这里会先执行advice,当没有advice的时候,currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1
这个时候就会执行目标方法
2、这里每次执行invoke方法的时候会把invocation传递进去,这样就会保证currentInterceptorIndex唯一性,又可以递归
本章结束