Spring AOP系列(四)—动态代理之CGLib动态代理
2020-10-01 09:25
162 查看
前言
JDK动态代理要求被代理的类必须实现接口,而生成的代理类也只能代理某个类接口定义的方法,这有很强的局限性。而CGLIB动态代理没有这个要求。简单来说,两者的区别有以下几点:
- Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类。
- ava动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效。
一、举个栗子
1.1 创建一个没有实现任何接口的类
package com.leng.proxy.dynamic.cglib; /** * @Classname UserServiceImpl * @Date 2020/9/22 21:58 * @Autor lengxuezhang */ public class UserServiceImpl { public void login() { System.out.println("用户登录......"); } public void sayHello() { System.out.println("Hello World!!!"); } }
想实现对
UserServiceImpl的动态代理,使用JDK动态代理是无法实现的,因为没有实现接口,
UserServiceImpl就是一个普通类。可以通过CGLIB实现代理,步骤如下:
- 首先实现一个
MethodInterceptor
,方法调用会被转发到该类的intercept()方法。 - 然后在需要使用
UserServiceImpl
的时候,通过CGLIB动态代理获取代理对象。
1.2 实现MethodInterceptor
接口
package com.leng.proxy.dynamic.cglib; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.Date; /** * @Classname LogInterceptor * @Date 2020/9/22 21:59 * @Autor lengxuezhang */ public class LogInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { before(); Object result = methodProxy.invokeSuper(o, objects); after(); return result; } // 预处理方法 private void before() { System.out.println(String.format("log start time [%s] ", new Date())); } // 后处理方法 private void after() { System.out.println(String.format("log end time [%s] ", new Date())); } }
intercept方法四个参数的含义如下:
obj: 代理类对象。
method: 被代理的类中的方法。
args: 调用方法需要的参数。
proxy: 生成的代理类对方法的“代理引用”。----?这句是什么意思?
用户需要实现MethodInterceptor接口,实现对方法的拦截。这一点与JDK动态代理中用户需要实现InvocationHandler接口类似。
1.3 客户端中使用CGLIB
代码如下:
package com.leng; import com.leng.proxy.dynamic.cglib.LogInterceptor; import com.leng.proxy.dynamic.cglib.UserServiceImpl; import org.springframework.cglib.proxy.Enhancer; /** * @Classname Client * @Date 2020/9/12 2:40 * @Autor lengxuezhang */ public class Client { public static void main(String[] args) { //CGLIB加强器,用于生成代理对象,类比JDK的Proxy Enhancer enhancer = new Enhancer(); //设置加强器继承被代理类 enhancer.setSuperclass(UserServiceImpl.class); //设置回调 enhancer.setCallback(new LogInterceptor()); //生成代理类对象 UserServiceImpl userService = (UserServiceImpl) enhancer.create(); //调用代理类对象中的方法时,会被我们实现的方法拦截器所拦截 userService.login(); userService.sayHello(); } }
Enhancer:
Enhancer是CGLIB中最常用的一个类,和Java1.3动态代理中引入的Proxy类差不多。但和Proxy不同的是,Enhancer既能够代理普通的class,也能够代理接口。Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。Enhancer不能拦截final方法,例如Object.getClass()方法,这是由于Java final方法语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。
Enhancer.setSuperclass用来设置父类型,
Enhancer.create(Object…)方法是用来创建增强对象的,其提供了很多不同参数的方法用来匹配被增强类的不同构造方法。(虽然类的构造方法只是Java字节码层面的函数,但是Enhancer却不能对其进行操作。Enhancer同样不能操作static或者final类)。我们也可以先使用Enhancer.createClass()来创建字节码(.class),然后用字节码动态的生成增强后的对象。
二、源码分析
2.1 生成指定类的Class对象字节数组
指定类是哪个类? 如上客户端中的调用代码,首先创建
Enhancer对象,设置
SuperClass父类(被代理类),然后调用
Enhancer对象的
create()方法。 这里对
Enhancer类需要特别提出一点:
Enhancer类也是
AbstractClassGenerator的子类,用处后面遇到会详细说。-
1. create()
/** * Generate a new class if necessary and uses the specified * callbacks (if any) to create a new object instance. * Uses the no-arg constructor of the superclass. * @return a new instance */ public Object create() { classOnly = false; argumentTypes = null; // 实际调用的方法 return createHelper(); } private Object createHelper() { //1.进行有效性验证 //1.1 callBack不能为空,也就是说至少要有一个callBack(callBack与代理类紧密相关) //1.2 有多个callBack时必须有callBackFilter preValidate(); //2.先根据KEY_FACTORY 以当前代理类的配置信息 生成一个组合Key,再利用这个组合Key,进行create Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null, ReflectUtils.getNames(interfaces), filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter), callbackTypes, useFactory, interceptDuringConstruction, serialVersionUID); this.currentKey = key; //根据生成的key创建代理对象 Object result = super.create(key); return result; }
接下来来到
AbstractClassGenerator类中的
create方法,这一步就是为了得到动态类的Class对象(Class的对象,认作A),之后通过反射生成具体的类的对象(A的对象)
protected Object create(Object key) { try { //1.获取当前类加载器,应用类加载器 ClassLoader loader = getClassLoader(); //2.缓存,一级缓存的key是类加载器,value是ClassLoaderData //2.1 cache中有则直接获取 Map<ClassLoader, ClassLoaderData> cache = CACHE; ClassLoaderData data = cache.get(loader); //2.2 cache中没有则生成 if (data == null) { synchronized (AbstractClassGenerator.class) { cache = CACHE; data = cache.get(loader); if (data == null) { Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache); data = new ClassLoaderData(loader); newCache.put(loader, data); CACHE = newCache; } } } this.key = key; //3.调用 get方法获取字节码,如果没有字节码,则会创建字节码(Class对象) Object obj = data.get(this, getUseCache()); //4.生成动态代理类 if (obj instanceof Class) { return firstInstance((Class) obj); } return nextInstance(obj); } catch (RuntimeException | Error ex) { throw ex; } catch (Exception ex) { throw new CodeGenerationException(ex); } }
如代码中的注释,该方法的3、4是核心的步骤,首先详细分析下3,我们进到
get方法中
public Object get(AbstractClassGenerator gen, boolean useCache) { //判断是否开启缓存,可直接设置:enhancer.setUseCache(false);默认为true if (!useCache) { return gen.generate(ClassLoaderData.this); } else { Object cachedValue = generatedClasses.get(gen); return gen.unwrapCachedValue(cachedValue); } }
关于 AbstractClassGenerator 的详细解析,可参考:
死磕cglib系列之二 AbstractClassGenerator缓存解析:https://blog.csdn.net/zhang6622056/article/details/87783480
这里我们直接来看
generate方法
protected Class generate(ClassLoaderData data) { Class gen; Object save = CURRENT.get(); CURRENT.set(this); try { // 1.判断有无classLoader ClassLoader classLoader = data.getClassLoader(); if (classLoader == null) { throw new IllegalStateException("ClassLoader is null while trying to define class " + getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " + "Please file an issue at cglib's issue tracker."); } // 2.生成动态代理的类名 synchronized (classLoader) { // 生成代理类名称 String name = generateClassName(data.getUniqueNamePredicate()); data.reserveName(name); this.setClassName(name); } if (attemptLoad) { try { gen = classLoader.loadClass(getClassName()); return gen; } catch (ClassNotFoundException e) { // ignore } } // 3.生成动态代理类的字节码 byte[] b = strategy.generate(this); String className = ClassNameReader.getClassName(new ClassReader(b)); ProtectionDomain protectionDomain = getProtectionDomain(); // 4.生成class文件 synchronized (classLoader) { // just in case // SPRING PATCH BEGIN gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain, contextClass); // SPRING PATCH END } return gen; } catch (RuntimeException | Error ex) { throw ex; } catch (Exception ex) { throw new CodeGenerationException(ex); } finally { CURRENT.set(save); } }
注释中的3的方法是
DefaultGeneratorStrategy中的方法如下:
public byte[] generate(ClassGenerator cg) throws Exception { DebuggingClassWriter cw = this.getClassVisitor(); this.transform((ClassGenerator)cg).generateClass(cw); return this.transform((byte[])cw.toByteArray()); }
注意,这里是一个访问者模式。
getClassVistor调用了asm的接口,生成了一个
DebuggingClassWriter对象。注意这里的cg就是之前的Enhancer实例,它overrided generateClass方法。 于是此时查看generateClass方法,又回到Enhance类:
public void generateClass(ClassVisitor v) throws Exception { Class sc = (superclass == null) ? Object.class : superclass; if (TypeUtils.isFinal(sc.getModifiers())) throw new IllegalArgumentException("Cannot subclass final class " + sc.getName()); List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors())); filterConstructors(sc, constructors); // Order is very important: must add superclass, then // its superclass chain, then each interface and // its superinterfaces. List actualMethods = new ArrayList(); List interfaceMethods = new ArrayList(); final Set forcePublic = new HashSet(); // 1.得到所有的方法,包括基类、接口 getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic); List methods = CollectionUtils.transform(actualMethods, new Transformer() { public Object transform(Object value) { Method method = (Method) value; int modifiers = Constants.ACC_FINAL | (method.getModifiers() & ~Constants.ACC_ABSTRACT & ~Constants.ACC_NATIVE & ~Constants.ACC_SYNCHRONIZED); if (forcePublic.contains(MethodWrapper.create(method))) { modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC; } return ReflectUtils.getMethodInfo(method, modifiers); } }); // 2.生成字节码,参数还是之前的classWriter // 2.1 这里的className就是之前生成的className ClassEmitter e = new ClassEmitter(v); if (currentData == null) { e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), Type.getType(sc), (useFactory ? TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) : TypeUtils.getTypes(interfaces)), Constants.SOURCE_FILE); } else { e.begin_class(Constants.V1_2, Constants.ACC_PUBLIC, getClassName(), null, new Type[]{FACTORY}, Constants.SOURCE_FILE); } List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance()); // 2.2 这些都是字段,之后我们会在生成的文件中看到 e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null); e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null); if (!interceptDuringConstruction) { e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null); } e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null); e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null); if (serialVersionUID != null) { e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID); } // 2.4 这里就是生成的callback,命名就是CGLIB&CALLBACK_在数组中的序号 for (int i = 0; i < callbackTypes.length; i++) { e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null); } // This is declared private to avoid "public field" pollution e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null); if (currentData == null) { // 2.5 filter在这里发生作用 emitMethods(e, methods, actualMethods); emitConstructors(e, constructorInfo); } else { emitDefaultConstructor(e); } emitSetThreadCallbacks(e); emitSetStaticCallbacks(e); emitBindCallbacks(e); if (useFactory || currentData != null) { int[] keys = getCallbackKeys(); emitNewInstanceCallbacks(e); emitNewInstanceCallback(e); emitNewInstanceMultiarg(e, constructorInfo); emitGetCallback(e, keys); emitSetCallback(e, keys); emitGetCallbacks(e); emitSetCallbacks(e); } e.end_class(); }
现在回到前面说到的“生成动态代理类对象”的方法:
//4.生成动态代理类 if (obj instanceof Class) { return firstInstance((Class) obj); }
进到
firstInstance方法,同样是Enhancer类中
/** * This method should not be called in regular flow. * Technically speaking {@link #wrapCachedClass(Class)} uses {@link EnhancerFactoryData} as a cache value, * and the latter enables faster instantiation than plain old reflection lookup and invoke. * This method is left intact for backward compatibility reasons: just in case it was ever used. * @param type class to instantiate * @return newly created proxy instance * @throws Exception if something goes wrong */ protected Object firstInstance(Class type) throws Exception { if (classOnly) { return type; } else { // 从名字也能看出来是利用了反射来生成代理类对象的 return createUsingReflection(type); } }
使用到了
ReflectUtils反射工具类中的方法,完成了动态代理对象的生成。
参考文献:
https://www.geek-share.com/detail/2617172721.html https://blog.csdn.net/woshilijiuyi/article/details/83448407 https://www.jianshu.com/p/20203286ccd9
相关文章推荐
- Spring系列之 (十一):AOP实现方式:动态代理的两个方式(JDK和Cglib)
- Spring AOP详解 、 JDK动态代理、CGLib动态代理
- Spring AOP中的JDK和CGLib动态代理哪个效率更高?
- Spring AOP中JDK和CGLib动态代理哪个更快?
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口
- Spring AOP中的JDK和CGLib动态代理哪个效率更高?
- Spring 静态代理、jdk与cglib动态代理 spring aop+ioc
- Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理-转载
- spring(AOP)静态代理、JDK动态代理、cglib实现代理
- SpringAOP学习笔记(4)CGLIB动态代理
- Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC
- 浅析Spring AOP源码(十三) jdk的动态代理和cglib的代理
- Spring面向切面编程(AOP)原理二之使用Cglib实现动态代理
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring学习总结——静态代理、JDK与CGLIB动态代理、AOP+IoC
- spring-aop原理讲解 JDK动态代理和CGLIB动态代理
- 【设计模式】代理模式那些事儿:静态代理,动态代理,JDK的动态代理,cglib,Spring AOP