• spring源码学习之AOP(二)


      接着上一篇中的内容!

    3、创建代理

    在获取了所有的bean对应的增强器之后,便可以进行代理的创建了
    org.springframework.aop.framework.autoproxy包下的AbstractAutoProxyCreator类中的createProxy方法

     1 protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
     2         @Nullable Object[] specificInterceptors, TargetSource targetSource) {
     3 
     4     if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
     5         AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
     6     }
     7 
     8     ProxyFactory proxyFactory = new ProxyFactory();
     9     // 获取当前类中的相关属性
    10     proxyFactory.copyFrom(this);
    11 
    12     // 决定对于给定的bean是否应该使用targetClass属性,而不是他的接口代理,检查proxyTargetClass设置以及preserveTargetClass属性
    13     if (!proxyFactory.isProxyTargetClass()) {
    14         if (shouldProxyTargetClass(beanClass, beanName)) {
    15             proxyFactory.setProxyTargetClass(true);
    16         }
    17         else {
    18             // 添加代理接口
    19             evaluateProxyInterfaces(beanClass, proxyFactory);
    20         }
    21     }
    22 
    23     Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    24     // 加入增强器
    25     proxyFactory.addAdvisors(advisors);
    26     // 设置要代理的类
    27     proxyFactory.setTargetSource(targetSource);
    28     // 定制代理
    29     customizeProxyFactory(proxyFactory);
    30     // 用来控制代理工厂被配置之后,是否还允许修改通知
    31     // 缺省值为false(即在代理被设置之后,不允许修改代理的配置)
    32     proxyFactory.setFrozen(this.freezeProxy);
    33     if (advisorsPreFiltered()) {
    34         proxyFactory.setPreFiltered(true);
    35     }
    36 
    37     return proxyFactory.getProxy(getProxyClassLoader());
    38 }

    对于代理类的创建和处理,spring委托给ProxyFactory处理,而此函数中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,这些初始化操作如下:
    (1)获取当前类中的属性
    (2)添加代理接口
    (3)封装advisor并加入到ProxyFactory中
    (4)设置要代理的类
    (5)当然spring中还为子类提供了定制的函数customizeProxyFactory,子类在此函数中对ProxyFactory进一步封装
    (6)进行获取代理操作

    其中封装advisor并加入到ProxyFactory中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的addAdvisor方法直接将增强器置入代理创建工厂中,
    但是将拦截器封装成增强器还是需要一定的逻辑的

    org.springframework.aop.framework.autoproxy包下的AbstractAutoProxyCreator类

     1 protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
     2     // Handle prototypes correctly...
     3     // 解析注册的所有的InterceptorName
     4     Advisor[] commonInterceptors = resolveInterceptorNames();
     5 
     6     List<Object> allInterceptors = new ArrayList<>();
     7     if (specificInterceptors != null) {
     8         // 加入拦截器
     9         allInterceptors.addAll(Arrays.asList(specificInterceptors));
    10         if (commonInterceptors.length > 0) {
    11             if (this.applyCommonInterceptorsFirst) {
    12                 allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
    13             }
    14             else {
    15                 allInterceptors.addAll(Arrays.asList(commonInterceptors));
    16             }
    17         }
    18     }
    19     if (logger.isDebugEnabled()) {
    20         int nrOfCommonInterceptors = commonInterceptors.length;
    21         int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
    22         logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
    23                 " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
    24     }
    25 
    26     Advisor[] advisors = new Advisor[allInterceptors.size()];
    27     for (int i = 0; i < allInterceptors.size(); i++) {
    28         // 拦截器进行封装转化为Advisor
    29         advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
    30     }
    31     return advisors;
    32 }

    wrap方法在org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry类中重写

     1 @Override
     2 public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
     3     // 如果要封装的对象本身就是Advisor类型的,无需做过多的处理
     4     if (adviceObject instanceof Advisor) {
     5         return (Advisor) adviceObject;
     6     }
     7     // 因为此封装方法只对Advisor和Advice两种类型有效,不是的话,就抛出异常
     8     if (!(adviceObject instanceof Advice)) {
     9         throw new UnknownAdviceTypeException(adviceObject);
    10     }
    11     Advice advice = (Advice) adviceObject;
    12     if (advice instanceof MethodInterceptor) {
    13         // So well-known it doesn't even need an adapter.
    14         // 如果是MethodInterceptor类型,则使用DefaultPointcutAdvisor类封装
    15         return new DefaultPointcutAdvisor(advice);
    16     }
    17     // 如果存在Advisor的适配器那么也同样需要进行封装
    18     for (AdvisorAdapter adapter : this.adapters) {
    19         // Check that it is supported.
    20         if (adapter.supportsAdvice(advice)) {
    21             return new DefaultPointcutAdvisor(advice);
    22         }
    23     }
    24     throw new UnknownAdviceTypeException(advice);
    25 }

    由于spring中涉及过多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor来进行代理的创建,完成了增强的封装过程,那么解析的
    最重要的一步就是代理的创建和获取了

    (1)创建代理

     1 // org.springframework.aop.framework.ProxyFactory类中的
     2 public Object getProxy(@Nullable ClassLoader classLoader) {
     3     return createAopProxy().getProxy(classLoader);
     4 }
     5 
     6 protected final synchronized AopProxy createAopProxy() {
     7     if (!this.active) {
     8         activate();
     9     }
    10     // 创建代理
    11     return getAopProxyFactory().createAopProxy(this);
    12 }
    13 // org.springframework.aop.framework.DefaultAopProxyFactory类对createAopProxy()方法进行了重写
    14 
    15 @Override
    16 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    17     if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    18         Class<?> targetClass = config.getTargetClass();
    19         if (targetClass == null) {
    20             throw new AopConfigException("TargetSource cannot determine target class: " +
    21                     "Either an interface or a target is required for proxy creation.");
    22         }
    23         if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    24             return new JdkDynamicAopProxy(config);
    25         }
    26         return new ObjenesisCglibAopProxy(config);
    27     }
    28     else {
    29         return new JdkDynamicAopProxy(config);
    30     }
    31 }

    从源码可以看出,spring中存在着两种代理JdkDynamicAopProxy和ObjenesisCglibAopProxy两种
    看一下createAopProxy方法中影响这spring使用何种代理的判断条件,也就是if中的条件
    (1)isOptimize
    用来控制通过CGLIB创建的代理是否使用激进的优化策略。除非了解AOP代理如何处理优化,否则不推荐使用这个设置,目前这个属性仅用于CGLIB代理,JDK代理无效
    (2)isProxyTargetClass
    这个属性为true时,目标类本身被代理而不是目标类的接口,如果这个属性设置为true,CGLIB代理将被创建,设置方式<aop:aspectj-autoproxy proxy-target-class="true" />
    (3)hasNoUserSuppliedProxyInterfaces
    是否存在代理接口

    JDK代理与CGLIB代理的总结:
      如果目标对象实现了接口,默认情况下会使用JDK动态代理实现AOP
      如果目标对象实现了接口,可以强制使用CGLIB实现AOP
      如果目标对象没有实现接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB代理之前切换

    (2)获取代理

      JDK代理使用案例

     1 // 创建业务接口,业务对外提供的接口,包含着业务可以对外提供的功能
     2 public interface UserService{
     3 
     4     // 目标方法
     5     public abstract void add();
     6 }
     7 
     8 // 创建业务接口实现类
     9 public class UserServiceImpl implements UserService {
    10 
    11     public void add(){
    12         System.out.println("---------add()----------");
    13     }
    14 }
    15 
    16 // 创建自定义的InvocationHandler,用于对接口提供的方法进行增强
    17 public class MyInvocationHandler implements InvocationHandler{
    18     private Object target;
    19     
    20     public MyInvocationHandler(Object target){
    21         super();
    22         this.target = target;
    23     }
    24     
    25     // 执行目标对象方法
    26     public Object invoke(Obejct proxy, Method method, Object[] args) throws Throwable {
    27         System.out.println("---------before()----------");
    28         Obejct result = method.invoke(target, args);
    29         System.out.println("---------after()----------");
    30         return result;
    31     }
    32     
    33     // 获取目标对象的代理对象
    34     public Object getProxy(){
    35         return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),target.getClass().getInterfaces(),this);
    36     }
    37 }
    38 
    39 // 测试类
    40 public class ProxyTest{
    41 
    42     @Test
    43     public void testProxy(){
    44         UserService userService = new UserServiceImpl();
    45         // 实例化InvocationHandler
    46         MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
    47         // 根据目标对象生成代理对象
    48         UserService proxy = (UserService) invocationHandler.getProxy();
    49         // 执行代理对象方法
    50         proxy.add();
    51     }
    52 }

    用起来很简单,这其实就是AOP的简单的实现,在目标方法的执行之前和执行之后进行了增强,spring的AOP实现其实也就是用了Proxy、InvocationHandler这两个类
    再次回顾一下使用JDK代理的方式,在整个创建过程中,对于InvocationHandler的创建是最为核心的,在自定义的InvocationHandler中需要重写三个函数
      构造函数,将代理对象传入
      invoke方法,此方法中实现了AOP增强的所有逻辑
      getProxy方法

    JdkDynamicAopProxy的getProxy()源码:
    org.springframework.aop.framework.JdkDynamicAopProxy类中

    1 @Override
    2 public Object getProxy(@Nullable ClassLoader classLoader) {
    3     if (logger.isDebugEnabled()) {
    4         logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    5     }
    6     Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    7     findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    8     return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    9 }

    JDKProxy的使用关键是创建自定义的InvocationHandler,而InvocationHandler中包含了需要覆盖的函数getProxy,并且JdkDynamicAopProxy还实现了InvocationHandler接口,
    因此,在该类中肯定存在一个重写的invoke方法,完成AOP的核心逻辑:invoke函数源码:

     1 @Override
     2 @Nullable
     3 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     4     Object oldProxy = null;
     5     boolean setProxyContext = false;
     6 
     7     TargetSource targetSource = this.advised.targetSource;
     8     Object target = null;
     9 
    10     try {
    11         // equals方法的处理
    12         if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
    13             // The target does not implement the equals(Object) method itself.
    14             return equals(args[0]);
    15         }
    16         // hash方法的处理
    17         else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
    18             // The target does not implement the hashCode() method itself.
    19             return hashCode();
    20         }
    21         else if (method.getDeclaringClass() == DecoratingProxy.class) {
    22             // There is only getDecoratedClass() declared -> dispatch to proxy config.
    23             return AopProxyUtils.ultimateTargetClass(this.advised);
    24         }
    25         else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
    26                 method.getDeclaringClass().isAssignableFrom(Advised.class)) {
    27             // Service invocations on ProxyConfig with the proxy config...
    28             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
    29         }
    30 
    31         Object retVal;
    32 
    33         // 有时候目标对象内部的自我调用将无法实施切面中的增强,则需要此属性暴露代理
    34         if (this.advised.exposeProxy) {
    35             // Make invocation available if necessary.
    36             oldProxy = AopContext.setCurrentProxy(proxy);
    37             setProxyContext = true;
    38         }
    39 
    40         // Get as late as possible to minimize the time we "own" the target,
    41         // in case it comes from a pool.
    42         target = targetSource.getTarget();
    43         Class<?> targetClass = (target != null ? target.getClass() : null);
    44 
    45         // Get the interception chain for this method.
    46         // 获取当前方法的拦截器链
    47         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    48 
    49         // Check whether we have any advice. If we don't, we can fallback on direct
    50         // reflective invocation of the target, and avoid creating a MethodInvocation.
    51         if (chain.isEmpty()) {
    52             // We can skip creating a MethodInvocation: just invoke the target directly
    53             // Note that the final invoker must be an InvokerInterceptor so we know it does
    54             // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
    55             // 如果没有发现拦截器链,那么直接调用切点方法
    56             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    57             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    58         }
    59         else {
    60             // We need to create a method invocation...
    61             // 将拦截器封装在ReflectiveMethodInvocation以便于其使用proceed进行链接表用拦截器
    62             MethodInvocation invocation =
    63                     new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    64             // Proceed to the joinpoint through the interceptor chain.
    65             // 执行拦截器链
    66             retVal = invocation.proceed();
    67         }
    68 
    69         // Massage return value if necessary.
    70         // 返回结果
    71         Class<?> returnType = method.getReturnType();
    72         if (retVal != null && retVal == target &&
    73                 returnType != Object.class && returnType.isInstance(proxy) &&
    74                 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
    75             // Special case: it returned "this" and the return type of the method
    76             // is type-compatible. Note that we can't help if the target sets
    77             // a reference to itself in another returned object.
    78             retVal = proxy;
    79         }
    80         else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
    81             throw new AopInvocationException(
    82                     "Null return value from advice does not match primitive return type for: " + method);
    83         }
    84         return retVal;
    85     }
    86     finally {
    87         if (target != null && !targetSource.isStatic()) {
    88             // Must have come from TargetSource.
    89             targetSource.releaseTarget(target);
    90         }
    91         if (setProxyContext) {
    92             // Restore old proxy.
    93             AopContext.setCurrentProxy(oldProxy);
    94         }
    95     }
    96 }

    上面的方法中最主要的就是创建了一个拦截器链,并使用ReflectiveMethodInvocation类进行了封装,而在ReflectiveMethodInvocation的proceed中实现了拦截器的逐一
    调用,那继续看proceed方法的源码,如何实现前置增强与后置增强的:

    此方法是在org.springframework.aop.framework.ReflectiveMethodInvocation类中进行重写的:

     1 @Override
     2 @Nullable
     3 public Object proceed() throws Throwable {
     4     //    We start with an index of -1 and increment early.
     5     // 执行完所有增强后,执行切点方法
     6     if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
     7         return invokeJoinpoint();
     8     }
     9 
    10     // 获取下一个要执行的拦截器
    11     Object interceptorOrInterceptionAdvice =
    12             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    13     if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    14         // Evaluate dynamic method matcher here: static part will already have
    15         // been evaluated and found to match.
    16         // 动态匹配
    17         InterceptorAndDynamicMethodMatcher dm =
    18                 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
    19         if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    20             return dm.interceptor.invoke(this);
    21         }
    22         else {
    23             // Dynamic matching failed.
    24             // Skip this interceptor and invoke the next in the chain.
    25             // 不匹配则不执行拦截器
    26             return proceed();
    27         }
    28     }
    29     else {
    30         // It's an interceptor, so we just invoke it: The pointcut will have
    31         // been evaluated statically before this object was constructed.
    32         /**
    33          * 普通拦截器则直接调用拦截器
    34          * 例如:
    35          * MethodBeforeAdviceIntercepter
    36          * AspectJAroundAdvice
    37          * AspectJAfterAdvice
    38          */
    39         // 将this作为参数传递以保证当前实例中调用链的执行
    40         return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    41     }
    42 }

      CGLIB代理使用案例

    CGLIB是一个强大的高性能的代码生成包。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
    看如何使用CGLIB
    需要导入外部net.sf.cglib.proxy包

     1 public class EnhancerDemo{
     2     public static void main(String[] args){
     3         Enhancer enhancer = new Enhancer();
     4         enhancer.setSupperclass(EnhancerDemo.class);
     5         enhancer.setCallback(new MethodInterceptorImpl());
     6         EnhancerDemo demo = (EnhancerDemo) enhancer.create();
     7         demo.test();
     8         System.out.println(demo);
     9     }
    10     
    11     public void test(){
    12         System.out.println("EnhancerDemo test()");
    13     }
    14     
    15     public static class MethodInterceptorImpl implements MethodInterceptor{
    16         @Override
    17         public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy){
    18             System.out.println("Before invoke" + method);
    19             Object result = proxy.invokeSuper(obj, args);
    20             System.out.println("After invoke" + method);
    21             return result;
    22         }
    23     }
    24 }

    完成CGLIB代理的类是委托给Cglib2AopProxy类去实现的,Cglib2AopProxy的入口应该是getProxy,也就是说Cglib2AopProxy类的getProxy中实现了Enhancer的创建和接口封装
    我就有点搞不懂了,作者从哪里搞出来一个Cglib2AopProxy,明明是CglibAopProxy,看getProxy的源码
    org.springframework.aop.framework.CglibAopProxy类中的getProxy

     1 @Override
     2 public Object getProxy(@Nullable ClassLoader classLoader) {
     3     if (logger.isDebugEnabled()) {
     4         logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
     5     }
     6 
     7     try {
     8         Class<?> rootClass = this.advised.getTargetClass();
     9         Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    10 
    11         Class<?> proxySuperClass = rootClass;
    12         if (ClassUtils.isCglibProxyClass(rootClass)) {
    13             proxySuperClass = rootClass.getSuperclass();
    14             Class<?>[] additionalInterfaces = rootClass.getInterfaces();
    15             for (Class<?> additionalInterface : additionalInterfaces) {
    16                 this.advised.addInterface(additionalInterface);
    17             }
    18         }
    19 
    20         // Validate the class, writing log messages as necessary.
    21         // 验证Class
    22         validateClassIfNecessary(proxySuperClass, classLoader);
    23 
    24         // Configure CGLIB Enhancer...
    25         // 创建和配置Enhancer
    26         Enhancer enhancer = createEnhancer();
    27         if (classLoader != null) {
    28             enhancer.setClassLoader(classLoader);
    29             if (classLoader instanceof SmartClassLoader &&
    30                     ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
    31                 enhancer.setUseCache(false);
    32             }
    33         }
    34         enhancer.setSuperclass(proxySuperClass);
    35         enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    36         enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    37         enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
    38 
    39         // 设置拦截器
    40         Callback[] callbacks = getCallbacks(rootClass);
    41         Class<?>[] types = new Class<?>[callbacks.length];
    42         for (int x = 0; x < types.length; x++) {
    43             types[x] = callbacks[x].getClass();
    44         }
    45         // fixedInterceptorMap only populated at this point, after getCallbacks call above
    46         enhancer.setCallbackFilter(new ProxyCallbackFilter(
    47                 this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    48         enhancer.setCallbackTypes(types);
    49 
    50         // Generate the proxy class and create a proxy instance.
    51         // 生成代理类和创建代理
    52         return createProxyClassAndInstance(enhancer, callbacks);
    53     }
    54     catch (CodeGenerationException | IllegalArgumentException ex) {
    55         throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
    56                 ": Common causes of this problem include using a final class or a non-visible class",
    57                 ex);
    58     }
    59     catch (Throwable ex) {
    60         // TargetSource.getTarget() failed
    61         throw new AopConfigException("Unexpected AOP exception", ex);
    62     }
    63 }

    以上函数完成的说明了spring中创建Enhancer的过程,这里最重要的是getCallbacks设置拦截器链,看getCallbacks的源码:
    org.springframework.aop.framework.CglibAopProxy类中:

     1 private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
     2     // Parameters used for optimization choices...
     3     // 对expose-proxy属性的处理
     4     boolean exposeProxy = this.advised.isExposeProxy();
     5     boolean isFrozen = this.advised.isFrozen();
     6     boolean isStatic = this.advised.getTargetSource().isStatic();
     7 
     8     // Choose an "aop" interceptor (used for AOP calls).
     9     // 将拦截器封装在DynamicAdvisedInterceptor中
    10     Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
    11 
    12     // Choose a "straight to target" interceptor. (used for calls that are
    13     // unadvised but can return this). May be required to expose the proxy.
    14     Callback targetInterceptor;
    15     if (exposeProxy) {
    16         targetInterceptor = (isStatic ?
    17                 new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
    18                 new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    19     }
    20     else {
    21         targetInterceptor = (isStatic ?
    22                 new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
    23                 new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    24     }
    25 
    26     // Choose a "direct to target" dispatcher (used for
    27     // unadvised calls to static targets that cannot return this).
    28     Callback targetDispatcher = (isStatic ?
    29             new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
    30 
    31     Callback[] mainCallbacks = new Callback[] {
    32             // 将拦截器链加入到Callback中
    33             aopInterceptor,  // for normal advice
    34             targetInterceptor,  // invoke target without considering advice, if optimized
    35             new SerializableNoOp(),  // no override for methods mapped to this
    36             targetDispatcher, this.advisedDispatcher,
    37             new EqualsInterceptor(this.advised),
    38             new HashCodeInterceptor(this.advised)
    39     };
    40 
    41     Callback[] callbacks;
    42 
    43     // If the target is a static one and the advice chain is frozen,
    44     // then we can make some optimizations by sending the AOP calls
    45     // direct to the target using the fixed chain for that method.
    46     if (isStatic && isFrozen) {
    47         Method[] methods = rootClass.getMethods();
    48         Callback[] fixedCallbacks = new Callback[methods.length];
    49         this.fixedInterceptorMap = new HashMap<>(methods.length);
    50 
    51         // TODO: small memory optimization here (can skip creation for methods with no advice)
    52         for (int x = 0; x < methods.length; x++) {
    53             List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
    54             fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
    55                     chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
    56             this.fixedInterceptorMap.put(methods[x].toString(), x);
    57         }
    58 
    59         // Now copy both the callbacks from mainCallbacks
    60         // and fixedCallbacks into the callbacks array.
    61         callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
    62         System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
    63         System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
    64         this.fixedInterceptorOffset = mainCallbacks.length;
    65     }
    66     else {
    67         callbacks = mainCallbacks;
    68     }
    69     return callbacks;
    70 }

    在getCallbacks中spring考虑了很多情况,但是对于我们来说,只需要理解最常用的就可以了,比如将advised属性封装在DynamicAdvisedInterceptor并加入在
    callbacks中,这么做的目的是什么,为什么会这么做?在前面的示例中,我们了解到CGLIB中对于方法的拦截是通过将自定义的拦截器(实现MethodInterceptor接口)加入
    Callback中并在调用代理的时候直接激活拦截器中的intercept方法来实现的,那么在getCallback中正是实现了这样的一个目的,DynamicAdvisedInterceptor继承自MethodInterceptor
    加入CallBack中后,再次调用代理时会直接调用DynamicAdvisedInterceptor中的intercept方法,所以,由此推断,对于CGLIB方式实现的代理,其核心逻辑在
    DynamicAdvisedInterceptor中的intercept方法,DynamicAdvisedInterceptor作为CglibAopProxy内部封装私有类,其在org.springframework.aop.framework.CglibAopProxy类中:

     1 @Override
     2 @Nullable
     3 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
     4     Object oldProxy = null;
     5     boolean setProxyContext = false;
     6     Object target = null;
     7     TargetSource targetSource = this.advised.getTargetSource();
     8     try {
     9         if (this.advised.exposeProxy) {
    10             // Make invocation available if necessary.
    11             oldProxy = AopContext.setCurrentProxy(proxy);
    12             setProxyContext = true;
    13         }
    14         // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
    15         target = targetSource.getTarget();
    16         Class<?> targetClass = (target != null ? target.getClass() : null);
    17         // 获取拦截链
    18         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    19         Object retVal;
    20         // Check whether we only have one InvokerInterceptor: that is,
    21         // no real advice, but just reflective invocation of the target.
    22         if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    23             // We can skip creating a MethodInvocation: just invoke the target directly.
    24             // Note that the final invoker must be an InvokerInterceptor, so we know
    25             // it does nothing but a reflective operation on the target, and no hot
    26             // swapping or fancy proxying.
    27             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    28             // 如果拦截链为空则直接激活原方法
    29             retVal = methodProxy.invoke(target, argsToUse);
    30         }
    31         else {
    32             // We need to create a method invocation...
    33             // 进入链中
    34             retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    35         }
    36         retVal = processReturnType(proxy, target, method, retVal);
    37         return retVal;
    38     }
    39     finally {
    40         if (target != null && !targetSource.isStatic()) {
    41             targetSource.releaseTarget(target);
    42         }
    43         if (setProxyContext) {
    44             // Restore old proxy.
    45             AopContext.setCurrentProxy(oldProxy);
    46         }
    47     }
    48 }

    上述的实现与JDK方式实现代理中的invoke方法基本相同,都是首先构造链,然后封装此链进行串联调用,区别就是在JDK代理中直接构造ReflectiveMethodInvocation类,而在
    CGLIB代理中使用CglibMethodInvocation,CglibMethodInvocation继承自ReflectiveMethodInvocation,但是process方法没有重写

    注意:spring还支持静态代理,这里没有写!!!不想写了

  • 相关阅读:
    常用CSS英文字体介绍
    LotusPhp学习四:Cookie 组件的使用
    VS 项目创建失败集合
    对于访问IIS元数据库失败的解决 和 服务器应用程序不可用 解决方案!
    SilverLight DataBinding绑定详解(学习笔记)
    基于WCF的即时通讯的设计与实现
    反编译Silverlight项目(转载)
    Silverlight 3中param参数列表汇总
    数据库LINQ TO SQL在Silverlight中的应用(WCF)学习笔记(一)
    Silverlight 自定义控件模板管理 (silverlight 学习笔记)
  • 原文地址:https://www.cnblogs.com/ssh-html/p/11296363.html
Copyright © 2020-2023  润新知