精华内容
下载资源
问答
  • cglib源码分析
    2020-05-10 21:13:55

    本文分下面三个部分来分析cglib动态代理的原理。

    1. cglib 动态代理示例
    2. 代理类分析
    3. Fastclass 机制分析

    一、cglib 动态代理示例

    public class Target{
        public void f(){
            System.out.println("Target f()");
        }
        public void g(){
            System.out.println("Target g()");
        }
    }
    
    public class Interceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args,    MethodProxy proxy) throws Throwable {
            System.out.println("I am intercept begin");
    //Note: 此处一定要使用proxy的invokeSuper方法来调用目标类的方法
            proxy.invokeSuper(obj, args);
            System.out.println("I am intercept end");
            return null;
        }
    }
    
    public class Test {
        public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\code");
             //实例化一个增强器,也就是cglib中的一个class generator
            Enhancer eh = new Enhancer();
             //设置目标类
            eh.setSuperclass(Target.class);
            // 设置拦截对象
            eh.setCallback(new Interceptor());
            // 生成代理类并返回一个实例
            Target t = (Target) eh.create();
            t.f();
            t.g();
        }
    }
    

    运行结果为:

    I am intercept begin
    Target f()
    I am intercept end
    I am intercept begin
    Target g()
    I am intercept end
    

    与JDK动态代理相比,cglib可以实现对一般类的代理而无需实现接口。在上例中通过下列步骤来生成目标类Target的代理类:

    1. 创建Enhancer实例
    2. 通过setSuperclass方法来设置目标类
    3. 通过setCallback 方法来设置拦截对象
    4. create方法生成Target的代理类,并返回代理类的实例

    二、代理类分析

    在示例代码中我们通过设置DebuggingClassWriter.DEBUG_LOCATION_PROPERTY的属性值来获取cglib生成的代理类。通过之前分析的命名规则我们可以很容易的在F:\code下面找到生成的代理类 Target$$EnhancerByCGLIB$$788444a0.class

    使用jd-gui进行反编译(由于版本的问题,此处只能显示部分代码,可以结合javap的反编译结果来进行分析),由于cglib会代理Object中的finalize,equals, toString,hashCode,clone方法,为了清晰的展示代理类我们省略这部分代码,反编译的结果如下:

    public class Target$$EnhancerByCGLIB$$788444a0 extends Target implements Factory
    {
        private boolean CGLIB$BOUND;
        private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
        private static final Callback[] CGLIB$STATIC_CALLBACKS;
        private MethodInterceptor CGLIB$CALLBACK_0;
        private static final Method CGLIB$g$0$Method;
        private static final MethodProxy CGLIB$g$0$Proxy;
        private static final Object[] CGLIB$emptyArgs;
        private static final Method CGLIB$f$1$Method;
        private static final MethodProxy CGLIB$f$1$Proxy;
        
        static void CGLIB$STATICHOOK1()
        {
          CGLIB$THREAD_CALLBACKS = new ThreadLocal();
          CGLIB$emptyArgs = new Object[0];
          Class localClass1 = Class.forName("net.sf.cglib.test.Target$$EnhancerByCGLIB$$788444a0");
          Class localClass2;
          Method[] tmp60_57 = ReflectUtils.findMethods(new String[] { "g", "()V", "f", "()V" }, (localClass2 = Class.forName("net.sf.cglib.test.Target")).getDeclaredMethods());
          CGLIB$g$0$Method = tmp60_57[0];
          CGLIB$g$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "g", "CGLIB$g$0");
          CGLIB$f$1$Method = tmp60_57[1];
          CGLIB$f$1$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "f", "CGLIB$f$1");
        }
        
        final void CGLIB$g$0()
        {
          super.g();
        }
        
        public final void g()
        {
          MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
          if (tmp4_1 == null)
          {
              CGLIB$BIND_CALLBACKS(this);
              tmp4_1 = this.CGLIB$CALLBACK_0;
          }
          if (this.CGLIB$CALLBACK_0 != null) {
              tmp4_1.intercept(this, CGLIB$g$0$Method, CGLIB$emptyArgs, CGLIB$g$0$Proxy);
          }
          else{
              super.g();
          }
        }
    }
    

    代理类(Target$$EnhancerByCGLIB$$788444a0)继承了目标类(Target),至于代理类实现的factory接口与本文无关,残忍无视。代理类为每个目标类的方法生成两个方法,例如针对目标类中的每个非private方法,代理类会生成两个方法,以g方法为例:一个是@Override的g方法,一个是CGLIB$g$0CGLIB$g$0相当于目标类的g方法)。我们在示例代码中调用目标类的方法t.g()时,实际上调用的是代理类中的g()方法。接下来我们着重分析代理类中的g方法,看看是怎么实现的代理功能。

    当调用代理类的g方法时,先判断是否已经存在实现了MethodInterceptor接口的拦截对象,如果没有的话就调用CGLIB\$BIND_CALLBACKS方法来获取拦截对象,CGLIB\$BIND_CALLBACKS的反编译结果如下:

    private static final void CGLIB$BIND_CALLBACKS(java.lang.Object);
    Code:
    0:   aload_0
    1:   checkcast       #2; //class net/sf/cglib/test/Target$$EnhancerByCGLIB$$788444a0
    4:   astore_1
    5:   aload_1
    6:   getfield        #212; //Field CGLIB$BOUND:Z
    9:   ifne    52
    12:  aload_1
    13:  iconst_1
    14:  putfield        #212; //Field CGLIB$BOUND:Z
    17:  getstatic       #24; //Field CGLIB$THREAD_CALLBACKS:Ljava/lang/ThreadLocal;
    20:  invokevirtual   #215; //Method java/lang/ThreadLocal.get:()Ljava/lang/Object;
    23:  dup
    24:  ifnonnull       39
    27:  pop
    28:  getstatic       #210; //Field CGLIB$STATIC_CALLBACKS:[Lnet/sf/cglib/proxy/Callback;
    31:  dup
    32:  ifnonnull       39
    35:  pop
    36:  goto    52
    39:  checkcast       #216; //class "[Lnet/sf/cglib/proxy/Callback;"
    42:  aload_1
    43:  swap
    44:  iconst_0
    45:  aaload
    

    为了方便阅读,等价的代码如下:

    private static final void CGLIB$BIND_CALLBACKS(Object o){
         Target$$EnhancerByCGLIB$$788444a0 temp_1 = (Target$$EnhancerByCGLIB$$788444a0)o;
         Object temp_2;
         Callback[] temp_3
         if(temp_1.CGLIB$BOUND == true){
             return;
         }
         temp_1.CGLIB$BOUND = true;
         temp_2 = CGLIB$THREAD_CALLBACKS.get();
         if(temp_2!=null){
             temp_3 = (Callback[])temp_2;
         }
         else if(CGLIB$STATIC_CALLBACKS!=null){
             temp_3 = CGLIB$STATIC_CALLBACKS;
         }
         else{
             return;
         }
         temp_1.CGLIB$CALLBACK_0 = (MethodInterceptor)temp_3[0];
         return;
     }
    

    CGLIB$BIND_CALLBACKS先从CGLIB$THREAD_CALLBACKS中get拦截对象,如果获取不到的话,再从CGLIB$STATIC_CALLBACKS来获取,如果也没有则认为该方法不需要代理。

    那么拦截对象是如何设置到CGLIB$THREAD_CALLBACKS或者 CGLIB$STATIC_CALLBACKS中的呢?

    在Jdk动态代理中拦截对象是在实例化代理类时由构造函数传入的,在cglib中是调用Enhancer的firstInstance方法来生成代理类实例并设置拦截对象的。firstInstance的调用轨迹为:

    1. Enhancer:firstInstance
    2. Enhancer:createUsingReflection
    3. Enhancer:setThreadCallbacks
    4. Enhancer:setCallbacksHelper
    5. Target$$EnhancerByCGLIB$$788444a0: CGLIB$SET_THREAD_CALLBACKS

    在第5步,调用了代理类的CGLIB$SET_THREAD_CALLBACKS来完成拦截对象的注入。下面我们看一下CGLIB$SET_THREAD_CALLBACKS的反编译结果:

    public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]);
      Code:
       0:   getstatic       #24; //Field CGLIB$THREAD_CALLBACKS:Ljava/lang/ThreadLocal;
       3:   aload_0
       4:   invokevirtual   #207; //Method java/lang/ThreadLocal.set:(Ljava/lang/Object;)V
       7:   return
    

    CGLIB$SET_THREAD_CALLBACKS方法中调用了CGLIB$THREAD_CALLBACKS的set方法来保存拦截对象,在CGLIB$BIND_CALLBACKS方法中使用了CGLIB$THREAD_CALLBACKS的get方法来获取拦截对象,并保存到CGLIB$CALLBACK_0中。这样,在我们调用代理类的g方法时,就可以获取到我们设置的拦截对象,然后通过 tmp4_1.intercept(this, CGLIB$g$0$Method, CGLIB$emptyArgs, CGLIB$g$0$Proxy)来实现代理。这里来解释一下intercept方法的参数含义:

    @para1 obj :代理对象本身

    @para2 method : 被拦截的方法对象

    @para3 args:方法调用入参

    @para4 proxy:用于调用被拦截方法的方法代理对象

    这里会有一个疑问,为什么不直接反射调用代理类生成的(CGLIB\$g\$0)来间接调用目标类的被拦截方法,而使用proxy的invokeSuper方法呢?这里就涉及到了另外一个点— FastClass 。

    三、Fastclass 机制分析

    Jdk动态代理的拦截对象是通过反射的机制来调用被拦截方法的,反射的效率比较低,所以cglib采用了FastClass的机制来实现对被拦截方法的调用。FastClass机制就是对一个类的方法建立索引,通过索引来直接调用相应的方法,下面用一个小例子来说明一下,这样比较直观:

    public class test10 {
       public static void main(String[] args){
           Test tt = new Test();
           Test2 fc = new Test2();
           int index = fc.getIndex("f()V");
           fc.invoke(index, tt, null);
       }
    }
    
    class Test{
       public void f(){
           System.out.println("f method");
       }
       
       public void g(){
           System.out.println("g method");
       }
    }
    class Test2{
       public Object invoke(int index, Object o, Object[] ol){
           Test t = (Test) o;
           switch(index){
           case 1:
               t.f();
               return null;
           case 2:
               t.g();
               return null;
           }
           return null;
       }
       
       public int getIndex(String signature){
           switch(signature.hashCode()){
           case 3078479:
               return 1;
           case 3108270:
               return 2;
           }
           return -1;
       }
    }
    

    上例中,Test2是Test的Fastclass,在Test2中有两个方法getIndex和invoke。在getIndex方法中对Test的每个方法建立索引,并根据入参(方法名+方法的描述符)来返回相应的索引。Invoke根据指定的索引,以ol为入参调用对象O的方法。这样就避免了反射调用,提高了效率。代理类(Target$$EnhancerByCGLIB$$788444a0)中与生成Fastclass相关的代码如下:

    Class localClass1 = Class.forName("net.sf.cglib.test.Target$$EnhancerByCGLIB$$788444a0");
    localClass2 = Class.forName("net.sf.cglib.test.Target");
    CGLIB$g$0$Proxy = MethodProxy.create(localClass2, localClass1, "()V", "g", "CGLIB$g$0");
    

    MethodProxy中会对localClass1和localClass2进行分析并生成FastClass,然后再使用getIndex来获取方法g 和 CGLIB\$g\$0的索引,具体的生成过程将在后续进行介绍,这里介绍一个关键的内部类:

    private static class FastClassInfo
        {
            FastClass f1; // net.sf.cglib.test.Target的fastclass
            FastClass f2; // Target$$EnhancerByCGLIB$$788444a0 的fastclass
            int i1; //方法g在f1中的索引
            int i2; //方法CGLIB$g$0在f2中的索引
        }
    

    MethodProxy 中invokeSuper方法的代码如下:

      FastClassInfo fci = fastClassInfo;
      return fci.f2.invoke(fci.i2, obj, args);
    

    当调用invokeSuper方法时,实际上是调用代理类的CGLIB$g$0方法,CGLIB$g$0直接调用了目标类的g方法。所以,在第一节示例代码中我们使用invokeSuper方法来调用被拦截的目标类方法。

    至此,我们已经了解cglib动态代理的工作原理,接下来会对cglib的相关源码进行分析。

    更多相关内容
  • CGLIB源码分析

    2021-07-19 14:34:13
    时序图 深入源码 回到Spring AOP的源码部分,AOP生成方式的选择是在DefaultAopProxyFactory中定义的。Spring 生成代理的方式有两种,一种是CGLIB一种是JDK动态代理。主要是通过代理类是否实现了接口来判断。 ...

    前言

    前面已经走完了Spring AOP的解析处理逻辑流程部分,接下来进入到具体的代理对象的代码生成阶段,揭开代理对象的神秘面纱。

    CGLIB动态代理

    首先是一个CGLIB使用的demo,代码如下:

    public class CglibEnhancerDemo {
    
    	public static void main(String[] args) {
    		Enhancer enhancer = new Enhancer();
    		enhancer.setSuperclass(TestBeanA.class);
    		enhancer.setCallback(new MyInterceptor());
    		TestBeanA testBeanA = (TestBeanA) enhancer.create();
    		String testStr = testBeanA.getTestStr();
    		System.out.println(testStr);
    	}
    
    	private static class MyInterceptor implements MethodInterceptor {
    		@Override
    		public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    			System.out.println("Before invoke method is: " + method);
    			Object result = methodProxy.invokeSuper(o, objects);
    			System.out.println("After invoke method is: " + method + " result is: " + result);
    			return result;
    		}
    	}
    }

    运行结果如下:

    > Task :spring-demo:CglibEnhancerDemo.main()
    Before invoke method is: public java.lang.String com.chudichen.spring.aop.TestBeanA.getTestStr()
    After invoke method is: public java.lang.String com.chudichen.spring.aop.TestBeanA.getTestStr() result is: testStrA
    testStrA

    可以看到执行的方法被自定义的Interceptor所拦截,并执行了增强的逻辑,CGLIB采用的是为代理的目标类生成子类的方式,具体的生成步骤是:

    1. 生成代理类的二进制字节码文件

    2. 加载二进制字节码,生成Class对象(例如使用Class.forName()方法)。

    3. 通过反射获取构造器创建出代理对象。

    时序图

     深入源码

    回到Spring AOP的源码部分,AOP生成方式的选择是在DefaultAopProxyFactory中定义的。Spring 生成代理的方式有两种,一种是CGLIB一种是JDK动态代理。主要是通过代理类是否实现了接口来判断。

    	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.");
    			}
    			/*
    			 * !!!!!!!!!!!!!!!!!!!!!!!!!!
    			 * 如果目标类是接口,则使用 JDK 动态代理,否则使用 CGLIB
    			 * !!!!!!!!!!!!!!!!!!!!!!!!!!
    			 */
    			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    				return new JdkDynamicAopProxy(config);
    			}
    			return new ObjenesisCglibAopProxy(config);
    		}
    		else {
    			return new JdkDynamicAopProxy(config);
    		}
    	}

    CGLIB代理

    进入到ObjenesisCglibAopProxy,可以看到它是继承自CglibAopProxy的,具体的准备增强器Enhancer以及设置拦截器链都是在CglibAopProxy中完成的。

    	public Object getProxy(@Nullable ClassLoader classLoader) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Creating CGLIB proxy: " + 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 (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
    				proxySuperClass = rootClass.getSuperclass();
    				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
    				for (Class<?> additionalInterface : additionalInterfaces) {
    					this.advised.addInterface(additionalInterface);
    				}
    			}
    
    			// 验证class
    			// Validate the class, writing log messages as necessary.
    			validateClassIfNecessary(proxySuperClass, classLoader);
    
    			// 获取增强器
    			// Configure CGLIB Enhancer...
    			Enhancer enhancer = createEnhancer();
    
    			// 为enhancer设置类加载器
    			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);
    			// 设置strategy策略器
    			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
    
    			Callback[] callbacks = getCallbacks(rootClass);
    			Class<?>[] types = new Class<?>[callbacks.length];
    			for (int x = 0; x < types.length; x++) {
    				types[x] = callbacks[x].getClass();
    			}
    			// 设置回调过滤器
    			// fixedInterceptorMap only populated at this point, after getCallbacks call above
    			enhancer.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 | IllegalArgumentException ex) {
    			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
    					": Common causes of this problem include using a final class or a non-visible class",
    					ex);
    		}
    		catch (Throwable ex) {
    			// TargetSource.getTarget() failed
    			throw new AopConfigException("Unexpected AOP exception", ex);
    		}
    	}

    其中比较重要的AOP逻辑都是在拦截器链中的,具体的过程是在getCallbacks()方法中,Callback的实现是由静态内部类DynamicAdvisedInterceptor完成的。

    	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    		// 获取expose-proxy属性设置
    		// Parameters used for optimization choices...
    		boolean exposeProxy = this.advised.isExposeProxy();
    		boolean isFrozen = this.advised.isFrozen();
    		boolean isStatic = this.advised.getTargetSource().isStatic();
    
    		// 将AOP拦截器封装在DynamicAdvisedInterceptor中
    		// Choose an "aop" interceptor (used for AOP calls).
    		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
    
    		// Choose a "straight to target" interceptor. (used for calls that are
    		// unadvised but can return this). May be required to expose the proxy.
    		Callback targetInterceptor;
    		if (exposeProxy) {
    			targetInterceptor = (isStatic ?
    					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
    					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    		}
    		else {
    			targetInterceptor = (isStatic ?
    					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
    					new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    		}
    
    		// Choose a "direct to target" dispatcher (used for
    		// unadvised calls to static targets that cannot return this).
    		Callback targetDispatcher = (isStatic ?
    				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
    
    		// 添加主要的拦截器链
    		Callback[] mainCallbacks = new Callback[] {
    				aopInterceptor,  // for normal advice
    				targetInterceptor,  // invoke target without considering advice, if optimized
    				new SerializableNoOp(),  // no override for methods mapped to this
    				targetDispatcher, this.advisedDispatcher,
    				new EqualsInterceptor(this.advised),
    				new HashCodeInterceptor(this.advised)
    		};
    
    		Callback[] callbacks;
    
    		// If the target is a static one and the advice chain is frozen,
    		// then we can make some optimizations by sending the AOP calls
    		// direct to the target using the fixed chain for that method.
    		if (isStatic && isFrozen) {
    			Method[] methods = rootClass.getMethods();
    			Callback[] fixedCallbacks = new Callback[methods.length];
    			this.fixedInterceptorMap = new HashMap<>(methods.length);
    
    			// TODO: small memory optimization here (can skip creation for methods with no advice)
    			for (int x = 0; x < methods.length; x++) {
    				Method method = methods[x];
    				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
    				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
    						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
    				this.fixedInterceptorMap.put(method, x);
    			}
    
    			// Now copy both the callbacks from mainCallbacks
    			// and fixedCallbacks into the callbacks array.
    			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
    			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
    			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
    			this.fixedInterceptorOffset = mainCallbacks.length;
    		}
    		else {
    			callbacks = mainCallbacks;
    		}
    		return callbacks;
    	}

    DynamicAdvisedInterceptor的作用

    DynamicAdvisedInterceptor为CGLIB中回调的默认实现.

    		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    			Object oldProxy = null;
    			boolean setProxyContext = false;
    			Object target = null;
    			// 要拦截的通知源
    			TargetSource targetSource = this.advised.getTargetSource();
    			try {
    				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();
    				Class<?> targetClass = (target != null ? target.getClass() : null);
    				// 获取拦截器链
    				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    				Object retVal;
    				// Check whether we only have one InvokerInterceptor: that is,
    				// no real advice, but just reflective invocation of the target.
    				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    					// 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 = methodProxy.invoke(target, argsToUse);
    				}
    				else {
    					// We need to create a method invocation...
    					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    				}
    				retVal = processReturnType(proxy, target, method, retVal);
    				return retVal;
    			}
    			finally {
    				if (target != null && !targetSource.isStatic()) {
    					targetSource.releaseTarget(target);
    				}
    				if (setProxyContext) {
    					// Restore old proxy.
    					AopContext.setCurrentProxy(oldProxy);
    				}
    			}
    		}

    拦截器链是通过DefaultAdvisorChainFactory中的getInterceptorsAndDynamicInterceptionAdvice方法来获取的。它的主要工作是:

    1. 先获取通知适配注册器

    2. 将注册器包装为可用的拦截器

    在这个过程中,DefaultAdvisorChainFactory是非常关键的角色。

    	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
    			Advised config, Method method, @Nullable Class<?> targetClass) {
    
    		/*
    		 * 调用DefaultAdvisorAdapterRegistry构造方法获取通知适配器注册器,包括:
    		 * 1. MethodBeforeAdviceAdapter
    		 * 2. AfterReturningAdviceAdapter
    		 * 3. ThrowsAdviceAdapter
    		 * Adapter添加进List中的顺序就是上面的顺序。
    		 */
    		// This is somewhat tricky... We have to process introductions first,
    		// but we need to preserve order in the ultimate list.
    		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    		// config也就是前面所说的ProxyFactory。从ProxyFactory中获取通知
    		Advisor[] advisors = config.getAdvisors();
    		List<Object> interceptorList = new ArrayList<>(advisors.length);
    		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    		Boolean hasIntroductions = null;
    
    		for (Advisor advisor : advisors) {
    			// 切面型通知
    			if (advisor instanceof PointcutAdvisor) {
    				// 将通知强转为切面
    				// Add it conditionally.
    				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
    				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
    					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
    					boolean match;
    					if (mm instanceof IntroductionAwareMethodMatcher) {
    						if (hasIntroductions == null) {
    							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
    						}
    						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
    					}
    					else {
    						match = mm.matches(method, actualClass);
    					}
    					if (match) {
    						/*
    						 * 通过通知适配注册器获取方法拦截器,这里返回的是四种拦截器,分别为:
    						 * ExposeInvocationInterceptor、AspectJAfterAdvice、AspectJAroundAdvice、MethodBeforeAdviceInterceptor
    						 */
    						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
    						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;
    	}

     DefaultAdvisorAdapterRegistry的主要工作有:

    1. 在构造方法中注册前置通知、后置通知和异常通知的适配器

    2. 包装Advisor

    3. 将Advisor包装为拦截器

    public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    
    	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
    
    
    	/**
    	 * 在构造方法里注册前置通知、后置通知和异常通知的适配器
    	 *
    	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
    	 */
    	public DefaultAdvisorAdapterRegistry() {
    		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    		registerAdvisorAdapter(new ThrowsAdviceAdapter());
    	}
    
    
    	@Override
    	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
    		// 如果封装对象本身就是Advisor,则无需做任何处理
    		if (adviceObject instanceof Advisor) {
    			return (Advisor) adviceObject;
    		}
    		// 如果不是Advice类型,则不能进行封装
    		if (!(adviceObject instanceof Advice)) {
    			throw new UnknownAdviceTypeException(adviceObject);
    		}
    		Advice advice = (Advice) adviceObject;
    		if (advice instanceof MethodInterceptor) {
    			// So well-known it doesn't even need an adapter.
    			return new DefaultPointcutAdvisor(advice);
    		}
    		for (AdvisorAdapter adapter : this.adapters) {
    			// Check that it is supported.
    			if (adapter.supportsAdvice(advice)) {
    				return new DefaultPointcutAdvisor(advice);
    			}
    		}
    		throw new UnknownAdviceTypeException(advice);
    	}
    
    	@Override
    	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    		List<MethodInterceptor> interceptors = new ArrayList<>(3);
    		// 获取通知
    		Advice advice = advisor.getAdvice();
    		// 判断是否是MethodInterceptor类型
    		if (advice instanceof MethodInterceptor) {
    			interceptors.add((MethodInterceptor) advice);
    		}
    		for (AdvisorAdapter adapter : this.adapters) {
    			if (adapter.supportsAdvice(advice)) {
    				interceptors.add(adapter.getInterceptor(advisor));
    			}
    		}
    		if (interceptors.isEmpty()) {
    			throw new UnknownAdviceTypeException(advisor.getAdvice());
    		}
    		return interceptors.toArray(new MethodInterceptor[0]);
    	}
    
    	@Override
    	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
    		this.adapters.add(adapter);
    	}
    
    }
    

    调用拦截器链

    获取完了拦截器链之后,在方法执行时就会调用拦截器链的增强逻辑了。这里又回到了DynamicAdvisedInterceptor的intercept(),当Advisor链为空的时候就直接执行目标对象的方法不进行代理了,不为空则需要调用proceed()进行代理逻辑处理了。

    这里仅显示关键部分的代码:

    				// 获取拦截器链
    				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    				Object retVal;
    				// Check whether we only have one InvokerInterceptor: that is,
    				// no real advice, but just reflective invocation of the target.
    				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    					// 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 = methodProxy.invoke(target, argsToUse);
    				}
    				else {
    					// We need to create a method invocation...
    					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    				}
    

    进入到ReflectiveMethodInvocation的逻辑部分,这里的执行过程为:

    1. 根据下标获取拦截器。

    2. 如果匹配就直接调用invoke执行拦截器,如果不匹配就继续调用proceed继续递归。

    3. 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) {
    			// Evaluate dynamic method matcher here: static part will already have
    			// been evaluated and found to match.
    			InterceptorAndDynamicMethodMatcher dm =
    					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
    			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
    			if (dm.methodMatcher.matches(this.method, 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.
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    	}

    后置通知的实现:

    public class AspectJAfterAdvice extends AbstractAspectJAdvice
    		implements MethodInterceptor, AfterAdvice, Serializable {
    
    	public AspectJAfterAdvice(
    			Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
    
    		super(aspectJBeforeAdviceMethod, pointcut, aif);
    	}
    
    
    	@Override
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		try {
    			return mi.proceed();
    		}
    		finally {
    			invokeAdviceMethod(getJoinPointMatch(), null, null);
    		}
    	}
    
    	@Override
    	public boolean isBeforeAdvice() {
    		return false;
    	}
    
    	@Override
    	public boolean isAfterAdvice() {
    		return true;
    	}
    
    }

    环绕通知实现逻辑:

    public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
    
    	public AspectJAroundAdvice(
    			Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
    
    		super(aspectJAroundAdviceMethod, pointcut, aif);
    	}
    
    
    	@Override
    	public boolean isBeforeAdvice() {
    		return false;
    	}
    
    	@Override
    	public boolean isAfterAdvice() {
    		return false;
    	}
    
    	@Override
    	protected boolean supportsProceedingJoinPoint() {
    		return true;
    	}
    
    	@Override
    	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);
    	}
    
    	/**
    	 * Return the ProceedingJoinPoint for the current invocation,
    	 * instantiating it lazily if it hasn't been bound to the thread already.
    	 * @param rmi the current Spring AOP ReflectiveMethodInvocation,
    	 * which we'll use for attribute binding
    	 * @return the ProceedingJoinPoint to make available to advice methods
    	 */
    	protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
    		return new MethodInvocationProceedingJoinPoint(rmi);
    	}
    
    }

    展开全文
  • 分析底层源码实现之前,我们先来试试,cglib能否代理接⼝,定义⼀个UserInterface接⼝ 然后利⽤cglib来代理⼀个接⼝: 也是可以正常运⾏的,那么⽤cglib代理⼀个类和代理⼀个接⼝的底层有什么区别呢?我们...

    cglib是⼀种动态代理技术,可以针对类来⽣成⼀个代理对象。 ⽐如,我们现有⼀个UserService类:

    现在利⽤cglib对UserService类中的test()⽅法进⾏增强:

     在分析底层源码实现之前,我们先来试试,cglib能否代理接⼝,定义⼀个UserInterface接⼝

     然后利⽤cglib来代理⼀个接⼝:

     

    也是可以正常运⾏的,那么⽤cglib代理⼀个类和代理⼀个接⼝的底层有什么区别呢?我们继续分析。

    我们知道,既然要⽣成⼀个代理对象,那么就肯定需要⼀个代理类,只不过当我们⽤cglib时,这个代理 类是由cglib⽣成的,那么我们能不能看到这个代理类是怎么⽣成的呢?

    可以!我们只需要在运⾏时加上:

    1 -Dcglib.debugLocation=D:\IdeaProjects\cglib\cglib\target\classes

    cglib就会将⽣成的代理类放到上⾯所指定的路径上。那么我们分别来看看cglib代理类和接⼝时所产⽣的 代理类是怎样的。

    UserService的代理类,我保留了类中⽐较关键的信息:

     UserInterface的代理类,我保留了类中⽐较关键的信息:

     

    可以发现这两种情况所产⽣的类区别不⼤,⽆⾮就是UserService代理类是UserService的⼦类, UserInterface代理类实现了UserInterface。

    我们可以发现在代理类中(以上两个任选⼀个),都存在⼀个test()⽅法和CGLIB$test$0()(以 UserService代理类举例⼦):

    test()⽅法内会去调⽤所设置的Callbacks中的intercept(),相当于执⾏增强逻辑,如果没有Callbacks, 则会执⾏super.test(),那么我们⾃然能想到,如果不设置Callbacks,那是不是就能正常执⾏呢?⽐如 这样:

     

    不好意思,运⾏这段代码时,cglib在构造代理对象时就会报⼀个没有Callbacks的空指针异常,所以我 们⽆法看到我们想看到的效果。

    但是这并不影响我们继续研究,我们再来看代理类中的另外⼀个⽅法:

     这个⽅法我们并不能直接调⽤,要通过所设置的Callback,也就是MethodInterceptor中的 MethodProxy对象来调⽤,MethodProxy对象表示⽅法代理,举个例⼦,假如UserService代理对象在 执⾏test()⽅法,那么当执⾏流程进⼊到intercept()⽅法时,MethodProxy对象表示的就是test()⽅法, 但是我们现在知道了在UserService类和UserService代理类中都有test()⽅法,所以MethodProxy对象 代理的就是这两个test(),⽐如:

    所以在执⾏methodProxy.invokeSuper()⽅法时,就会去执⾏CGLIB$test$0()⽅法。

    我们来总结⼀下cglib的⼤概⼯作原理是:cglib会根据所设置的Superclass,⽣成代理类作为其⼦类, 并且会重写Superclass中的⽅法,Superclass中的某⼀个⽅法,⽐如test(),相应的在代理类中会对应 两个⽅法,⼀个是重写的test(),⽤来执⾏增强逻辑,⼀个是CGLIB$test$0(),会直接调⽤ super.test(),是让MethodProxy对象来⽤的。

     

    那接下来的问题就是:

    1.代理类是怎么⽣成的?

    2. MethodProxy是怎么实现的?

    我们下篇⽂章⻅。

    展开全文
  • 其实我们如果看到了cglib所⽣成的代理类之后,其实就不难猜测,cglib是如何去⽣成代理类了,我们看 ⼀个完整的代理类: 我们发现,UserService代理类既继承了UserService类,也实现了Factory接⼝,从⽽...

    其实我们如果看到了cglib所⽣成的代理类之后,其实就不难猜测,cglib是如何去⽣成代理类了,我们看 ⼀个完整的代理类:

     

     

     

     

     

     我们发现,UserService代理类既继承了UserService类,也实现了Factory接⼝,从⽽代理中就需要去 实现Factory接⼝中的⼏个⽅法:

      

     我们可以发现newInstance()⽅法会重新⽣成⼀个代理对象,setCallbacks()和getCallbacks()可以⽤来 设置或获取增强逻辑。

    我们还发现,不仅只有test()⽅法会⽣成对应的两个⽅法,其他⽅法也会⽣成,⽐如:

    1. equals()

    2. toString()

    3. hashCode()

    4. clone()

    对于这些⽅法的实现上篇⽂章已经有所介绍了,所以我们再看⼀下⼀下代理类中还有什么代码是我们不 熟悉的:

     

     

     

     我们发现代理中有很多的属性,仔细阅读可以发现,这些属性中很多都是针对某个⽅法的Method对象 和MethodProxy对象,我们先把equals等所对应的先去掉:

     

     

     代理类中有⼀个代理块,会调⽤CGLIB$STATICHOOK1(),这个⽅法主要就是给属性赋值,⽐如:

    1. 构造⼀个ThreadLocal对象给CGLIB$THREAD_CALLBACKS属性

    2. 获取UserService类中的test⽅法的Method对象给CGLIB$test$0$Method属性

    3. 构造test()⽅法所对应的MethodProxy对象给CGLIB$test$0$Proxy属性

    另外,代理类中还有⼀些其他⽅法,但是我看了源码后,发现有⼏个⽅法它只是⽣成了,并没有被调⽤ 到,其中有⼀个⽅法是cglib在⽣成代理对象后,会主动调⽤的⼀个⽅法,这个⽅法是 CGLIB$SET_THREAD_CALLBACKS,我把其他⼏个不⽤的⽅法去掉:

     

     这样,我们就可以更加理解这个代理类了,⼤致流程是:

    1. cglib先⽣成代理类

    2. 然后调⽤构造⽅法得到代理对象

    3. 然后cglib调⽤代理对象的CGLIB$SET_THREAD_CALLBACKS()⽅法,把程序员所设置的 Callbacks设置到CGLIB$THREAD_CALLBACKS这个ThreadLocal中

    4. 后续代理对象在执⾏test()⽅法时,就会从CGLIB$THREAD_CALLBACKS拿到所设置的 Callbacks,调⽤其intercept()⽅法

    ⽽代理类的⽣成逻辑就是:

    1. 先⽣成类的定义,实现UserService和Factory接⼝

    2. 根据UserService类中的⽅法⽣成代理类中对应的⽅法和属性

    3. ⽣成⼀些辅助的属性和⽅法

    具体源码就不去分析了,感兴趣的可以⾃⼰花时间去啃了。

    ⽂章到这⾥,还有还有⼀个点没分析,就是MethodProxy对象,下篇⽂章继续。

    展开全文
  • (1)如果为true,那么使用cglib的动态代理。 (2)如果为true为false或这不设置,那么aop根据类是否继承接口决定用哪一种代理方式。 那么cglib的代理方式是怎么实现的呢,一起来探究一下: jdk的动态代理是用...
  • Cglib源码分析 invoke和invokeSuper的差别

    千次阅读 多人点赞 2018-03-17 17:06:20
    本文重在源码分析Cglib的使用不再复述。 //被代理类 public class InfoDemo { public void welcome (String person){ System.out.println("welcome :" + person); } } public class ...
  • cglib源码分析--转

    2019-09-27 03:41:48
    前段时间在工作中,包括一些代码阅读过程中,spring aop经常性的会看到cglib中的相关内容,包括BeanCopier,BulkBean,Enancher等内容,以前虽大致知道一些内容,原理是通过bytecode,但没具体深入代码研究,只知其...
  • 原文... Cglib的实例 本文重在源码分析Cglib的使用不再复述。 //被代理类 public class InfoDemo { public void welcome (String person){ System.out.pr...
  • public class MyTest { public static void main(String[] args) { //动态代理创建的class文件... //通过cglib动态代理获取代理对象的过程,创建调用的对象,在后续创建过程中EnhanceKey的对象,所以在进行enhance.
  • 前⾯介绍到MethodProxy对象,表示⼀个⽅法的代理,⽐如UserSerivce中的test()⽅法,在对应的代理 类中会有对应的两个⽅法: ⽽MethodProxy对象代理...2. sig2,表示CGLIB$test$0⽅法 3. createInfo,表示Us...
  • CgLib中AOP的实现是基于org.springframework.cglib.proxy包中Enhancer和MethodInterceptor(是CgLib包中的)两个接口来实现的。创建增强器Enhancer,并配置其callback为自定义的MethodInterceptor,然后创建代理。...
  • Cglib源码解析

    千次阅读 2018-02-27 21:47:34
    Cglib(Code Generator Library)是一个 java字节码生成工具,...本系列文章分析cglib源码实现。一、基本框架ClassGenerator是Cglib的核心接口,其中核心方法generateClass方法用于产生目标类;public interface Cla...
  • cglib是一个java 字节码的生成工具,它是对asm的进一步封装,提供了一系列class generator。研究cglib主要是因为它也提供了动态代理功能,这点和jdk的动态代理类似。 一、 Cache的创建 与jdk动态代理一样,cglib...
  • cglib动态代理 给出一个例子,再做分析 目标类 public class AliSmsService { public String send(String message) { System.out.println("send message:" + message); return message; } } 实现一个 ...
  • 结合生成的class文件是一个学习cglib的比较好的方法。在cglib中,生成的class文件默认只存储在内存中,我们可以在代码中加入下面语句来获取class file。 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_...
  • 目录 一、使用方式 1.业务方法类 2.实现代理方法 3.使用场景分析 3.1.使用CGLIB代理执行非接口实现类HelloWorld ...3.2.使用CGLIB代理执行接口实现类UserServiceImpl ...2.CGLIB代理源码分析 2.1创建代理对象 2.2调
  • cglib中生成类的工作是由AbstractClassGenerator的create方法使用相应的生成策略完成,具体代码如下: private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE; byte[] b = strategy.generate...
  • Spring | Aop核心 | Cglib源码详细解析

    千次阅读 2018-10-27 23:37:05
    概述 很多时候在编译时期不能决定具体的对象类型,无法生成所需要的字节码。只能在运行时期,根据传入的实例,来生成字节码。这就是动态代理要解决的问题...Spring Aop中的代理生成方式采用了jdk动态代理和cglib...
  • 一、前言 ...二、JDK动态代理源码分析 下面先来看下我们一般是如何使用JDK动态代理的。 /** * @author maoqichuan * @date 2022年03月22日 18:42 */ public class CalculatorProxy { public s...
  • NULL 博文链接:https://zhangyu84849467.iteye.com/blog/2278744
  • cglib动态代理源码解析 超级详细

    千次阅读 2019-05-13 20:31:20
    一、CGLIB动态代理实例 小A同学想要找女朋友,自己又不好意思,所以需要一个媒婆帮助他找对象,媒婆作为小A的代理,下面我们使用cglib动态代理,来用代码实现下: xiaoA: public class XiaoA { public void ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,630
精华内容 5,452
关键字:

cglib源码分析