spring aop怎么实现_完全读懂Spring框架之AOP实现原理

深入分析Spring框架中AOP与动态代理的整合原理

从本文可以了解到什么

  1. Spring的核心之一AOP具体是如何实现的
  2. Spring AOP使用了哪些动态代理方式
  3. 如何使用Spring AOP创建代理对象
  4. Spring有哪些代理切入方式,如何增加切面
  5. 在Spring之外有哪些代理方式
  6. Spring的各类注解如@Async等,是如何生效的

等等... 你想了解的内容,都会在本文进行呈现。

涉及到的相关源码都有中文注释,让你一次看个明白。

做好准备,正文开始了哦

Spring AOP动态代理支持的核心

  1. jdk动态代理:java.lang.reflect.InvocationHandler

对应的方法拦截器:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

调用时使用method.invoke(Object, args)

该动态代理是基于接口的动态代理,所以并没有一个原始方法的调用过程,整个方法都是被拦截的。

  1. 通过cglib动态创建类进行动态代理。org.springframework.cglib.proxy包下的原生接口,同net.sf.cglib.proxy包下的接口,都是源自cglib库。Spring内部的cglib动态代理使用了这种方式。

对应的方法拦截器:

org.springframework.cglib.proxy.Callback、 org.springframework.cglib.proxy.MethodInterceptor

public interface MethodInterceptor extends Callback { Object intercept(Object obj, Method m, Object[] args, MethodProxy mp) throws Throwable}

调用时,使用mp.invoke(Object obj, Object[] args)调用其他同类对象的原方法或者mp.invokeSuper(Object obj, Object[] args)调用原始(父类)方法。

  1. org.aopalliance的拦截体系

该包是AOP组织下的公用包,用于AOP中方法增强和调用。相当于一个jsr标准,只有接口和异常。在AspectJ、Spring等AOP框架中使用。

对应的方法拦截器org.aopalliance.intercept.MethodInterceptor:

public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation inv) throws Throwable;}

调用时使用inv.proceed()调用原始方法。

附aopalliance包介绍:

整个包的结构

a948ed85df521912a903f7c0fb424512.png

详细介绍:

  1. Advice
  2. 增强器标记接口
  3. Interceptor
  4. 拦截器,Advice的子接口,标记拦截器。拦截器是增强器的一种。
  5. MethodInterceptor
  6. 方法拦截器,Interceptor的子接口,拦截方法并处理。
  7. ConstructorInterceptor
  8. 构造器拦截器,Interceptor的子接口,拦截构造器并处理。
  9. Joinpoint
  10. 连接点。在拦截器中使用,封装了原方法调用的相关信息,如参数、原对象信息,以及直接调用原方法的proceed方法。
  11. Invocation
  12. Joinpoint的子类,添加了获取调用参数方法。
  13. MethodInvocation
  14. Invocation的子类,包含了获取调用方法的方法。
  15. ConstructorInvocation
  16. Invocation的子类,包含了获取构造器的方法。

Spring AOP框架的整合

先看一下通过Spring生成代理对象的代码:

// 生成基于实例的代理public Object createProxy(Object bean, Advice advice) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(bean); proxyFactory.addAdvice(advice); return proxyFactory.getProxy();}// 生成基于接口的代理public T createProxy(Class interface, Interceptor interceptor) { T proxy = new ProxyFactory(interface, interceptor).getProxy(); // 或者ProxyFactory.getProxy(interface, interceptor).getProxy(); return proxy;}

针对上面的代码,结合源码进行分析,得到整个代理对象的创建过程。

准备:过程中出现的对象

  1. AopProxyFactory接口
  2. AopProxy代理工厂类,用于生成代理对象AopProxy。
public interface AopProxyFactory { AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;}
  1. AopProxy
  2. 代表一个AopProxy代理对象,可以通过这个对象构造代理对象实例。
public interface AopProxy { Object getProxy(); Object getProxy(ClassLoader classLoader);}
  1. Advised接口
  2. 代表被Advice增强的对象,包括添加advisor的方法、添加advice等的方法。
  3. ProxyConfig类
  4. 一个代理对象的配置信息,包括代理的各种属性,如基于接口还是基于类构造代理。
  5. AdvisedSupport类
  6. 对Advised的构建提供支持,Advised的实现类以及ProxyConfig的子类。
  7. ProxyCreatorSupport类
  8. AdvisedSupport的子类,创建代理对象的支持类,内部包含AopProxyFactory工厂成员,可直接使用工厂成员创建Proxy。
  9. ProxyFactory类
  10. ProxyCreatorSupport的子类,用于生成代理对象实例的工厂类,生成代码参考下面。
  11. Advisor接口
  12. 代表一个增强器提供者的对象,内部包含getAdvice方法获取增强器。
  13. AdvisorChainFactory接口
  14. 获取增强器链的工厂接口。提供方法返回所有增强器,以数组返回。
  15. Pointcut接口
  16. 切入点,用于匹配类与方法,满足切入点的条件是才插入advice。相关接口:ClassFilter、MethodMatcher。

类图如下:

945476b3179527c701a5466603f62fd6.png

分析:结合源码分析创建过程

以上准备做完之后,就可以看源码了,从获取代理对象的实例入口ProxyFactory.getProxy()开始:

public Object getProxy() { // 创建AopProxy对象再获取代理对象实例return createAopProxy().getProxy();}// createAopProxy方法在父类ProxyCreatorSupport中protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}// 先获取AopProxy的工厂对象,再把自己作为createAopProxy的参数AdvisedSupport传进去,用自己作为代理对象的配置return getAopProxyFactory().createAopProxy(this);}

代理对象实例最终是使用AopProxy.getProxy()得到的,他的调用是在AopProxyFactory.createAopProxy(AdvisedSupport config,createAopProxy有两个结果。一个是基于接口的JDK动态代理JdkDynamicAopProxy,一个是基于CGLib的生成类代理ObjenesisCglibAopProxy。源码如下:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {@Overridepublic 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)) { // 如果目标类是接口,或者已经是Jdk的动态代理类,则创建jdk动态代理return new JdkDynamicAopProxy(config);}// 否则创建Cglib动态代理return new ObjenesisCglibAopProxy(config);}else { // 如果声明创建Jdk动态代理则返回Jdk动态代理 return new JdkDynamicAopProxy(config);}}}

传入的AdvisedSupport config中包含了需要注册的Method拦截器,AopProxy会保存这个config为advised对象。

基于JDK的动态代理

JdkDynamicAopProxy中getProxy会返回:

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, true);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);// 返回代理对象的实例return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

自己作为InvocationHandler注册,看他的invoke方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class> targetClass = null;Object target = null;try {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.// 没有声明equals方法,调用equals方法时,委托调用。return equals(args[0]);}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.// 没有声明hashCode方法,调用hashCode方法时,委托调用。return hashCode();}else if (method.getDeclaringClass() == DecoratingProxy.class) {// There is only getDecoratedClass() declared -> dispatch to proxy config.// 如果调用的方法是DecoratingProxy中的方法,因为其中只有一个getDecoratedClass方法,这里直接返回被装饰的Class即可return AopProxyUtils.ultimateTargetClass(this.advised);}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// 代理不是不透明的,且是接口中声明的方法,且是Advised或其父接口的方法,则直接调用构造时传入的advised对象的相应方法// Service invocations on ProxyConfig with the proxy config...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;if (this.advised.exposeProxy) {// Make invocation available if necessary. // 如果暴露代理,则用AopContext保存当前代理对象。用于多级代理时获取当前的代理对象,一个有效应用是同类中调用方法,代理拦截器会无效。可以使用AopContext.currentProxy()获得代理对象并调用。oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}// Get the interception chain for this// 这里是关键,获得拦截链chain,是通过advised对象,即config对象获得的。method.List 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对象,用于链式调用拦截器链chain中的拦截器。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())) {// 处理返回值// 如果返回结果是this,即原始对象,且方法所在类没有标记为RawTargetAccess(不是RawTargetAccess的实现类或者子接口),则返回代理对象。// 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);}}}

注册的Method拦截器都是通过AdvisedSupport这个config对象的addAdvice或者addAdvisor注册进去的。

public void addAdvice(int pos, Advice advice) throws AopConfigException {Assert.notNull(advice, "Advice must not be null");if (advice instanceof IntroductionInfo) {// We don't need an IntroductionAdvisor for this kind of introduction:// It's fully self-describing.// 如果是引介,则加入引介advisor。(新增功能)addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));}else if (advice instanceof DynamicIntroductionAdvice) {// We need an IntroductionAdvisor for this kind of introduction.// jdk动态代理不支持动态引介throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");}else { // 把advice转换为advisor并添加,目标是DefaultPointcutAdvisor。addAdvisor(pos, new DefaultPointcutAdvisor(advice));}}

其实也是把advice转成了advisor注册的。 看下最上面invoke方法中有一个方法调用:

List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class> targetClass) {MethodCacheKey cacheKey = new MethodCacheKey(method);List cached = this.methodCache.get(cacheKey);if (cached == null) { // 其实是通过advisorChainFactory工厂对象获得的cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);this.methodCache.put(cacheKey, cached);}return cached;}

是通过AdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法获取的,也把config对象传入了,且加的有缓存。其实是通过method获取该method对应的advisor。下面是他的唯一实现:

public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {@Overridepublic List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class> targetClass) {// This is somewhat tricky... We have to process introductions first,// but we need to preserve order in the ultimate list.List interceptorList = new ArrayList(config.getAdvisors().length);Class> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();for (Advisor advisor : config.getAdvisors()) {if (advisor instanceof PointcutAdvisor) {// Add it conditionally.PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {if (mm.isRuntime()) {// Creating a new object instance in the getInterceptors() method// isn't a problem as we normally cache created chains.for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}}}else if (advisor instanceof IntroductionAdvisor) {IntroductionAdvisor ia = (IntroductionAdvisor) advisor;if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}else {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}return interceptorList;}/** * Determine whether the Advisors contain matching introductions. */private static boolean hasMatchingIntroductions(Advised config, Class> actualClass) {for (int i = 0; i < config.getAdvisors().length; i++) {Advisor advisor = config.getAdvisors()[i];if (advisor instanceof IntroductionAdvisor) {IntroductionAdvisor ia = (IntroductionAdvisor) advisor;if (ia.getClassFilter().matches(actualClass)) {return true;}}}return false;}}

上面包括了各种对Advisor包装,通过Pointcut等的判断把Advisor中的Advice包装成MethodInterceptor、InterceptorAndDynamicMethodMatcher或者Interceptor。

之后在调用方法前,又把chain转换为了aopalliance体系的的MethodInvocation。

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

最终执行的是retVal = invocation.proceed()。 在ReflectiveMethodInvocation的proceed方法中,有整个拦截器链的责任链模式的执行过程,可以仔细看看,通过责任链序号方式执行的。

public Object proceed() throws Throwable {//We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // 链全部执行完,再次调用proceed时,返回原始对象方法调用执行结果。递归的终止。return invokeJoinpoint();}Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 用currentInterceptorIndex记录当前的interceptor位置,初值-1,先++再获取。当再拦截器中调用invocation.proceed()时,递归进入此方法,索引向下移位,获取下一个拦截器。if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // 如果是InterceptorAndDynamicMethodMatcher则再执行一次动态匹配// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { // 匹配成功,执行return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 匹配失败,跳过该拦截器,递归调用本方法,执行下一个拦截器。return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.// 如果是interceptor,则直接调用invoke。把自己作为invocation,以便在invoke方法中,调用invocation.proceed()来执行递归。或者invoke中也可以不执行invocation.proceed(),强制结束递归,返回指定对象作为结果。return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

基于Cglib的动态代理

看另外一种情况,Cglib的代理类:

ObjenesisCglibAopProxy继承自CglibAopProxy,整体对外暴露的接口和方法是与上面一致的,只有其真实实现换成了Cglib而已。

public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());}try {Class> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class> proxySuperClass = rootClass;if (ClassUtils.isCglibProxyClass(rootClass)) {proxySuperClass = rootClass.getSuperclass();Class>[] additionalInterfaces = rootClass.getInterfaces();for (Class> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...// 使用cglib库的enhancer,配置之后生成代理对象实例Enhancer enhancer = 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);// 设置类生成策略,直接生成类的字节码byte[],可以深入研究enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));  // 获取所有的callback,此时callback是cglib 的,getCallbacks中会把advisors封装成callback传入Callback[] callbacks = getCallbacks(rootClass);Class>[] types = new Class>[callbacks.length];// 生成callback类型数组for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call above// 加入是否需要进行callback的过滤器,根据filter的返回的int值,cglib会执行不同的callback,索引分别对应上面的callback数组的索引:// 0:AOP_PROXY、1:INVOKE_TARGET、2:NO_OVERRIDE、3:DISPATCH_TARGET、4:DISPATCH_ADVISED、5:INVOKE_EQUALS、6:INVOKE_HASHCODEenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值