Java代理模式——CGLIB动态代理
对于动态代理,如果没有定义代理类接口,而只是定义了代理类,那么此时JDK动态代理就无法使用了,因为JDK动态代理要求必须定义接口,它是对接口进行代理的,现在没有定义接口,那么自然就不能使用JDK动态代理了。
这时,我们就可以使用CGLIB动态代理来实现。
CGLIB是一个功能强大,高性能的代码生成包(CGLIB就是用来生成代码的,它也是在内存中动态的去生成的)
因为CGLIB是第三方提供的包,所以我们需要在maven工程中引入对应jar包:
<!--CGLIB--> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
接下来,CGLIB动态代理代码实现:
新建被代理类,我们这里用NaiKeCloth(耐克服装厂)举例。此时并不需要再新建Cloth接口,因为我们现在是要使用CGLIB进行代理
package com.hxk.pattern.proxy.cglib_proxy.lx; /** * 被代理类:耐克服装厂 * * @author *** * @create 2022-05-20 20:17 */ public class NaiKeCloth { public void makeCloth(String type){ System.out.println("制作服装:" + type); } public String brand(){ return "我的品牌是:耐克"; } }
新建工厂类,即ProxyFactory,该工厂就是用来获取代理对象的,所以我们应该在该工厂类中定义一个获取代理对象的方法,此时,使用CGLIB进行代理的话,获得的代理类就是目标对象所属类的子类。
使用CGLIB来进行代理:
- 创建Enhancer类对象,该类类似于JDK动态代理中的Proxy类。它就是用来获取代理对象的。注意该类是属于CGLIB里面的,所以我们要导入相对应的包。
- 设置父类的字节码对象。使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的。
- 设置回调函数。
ProxyFactory代码实现:
package com.hxk.pattern.proxy.cglib_proxy.lx; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @author *** * @create 2022-05-20 20:19 */ public class ProxyFactory<T> implements MethodInterceptor { private T obj; public ProxyFactory(T obj) { this.obj = obj; } public T getProxy(){ // 1. 创建Enhancer类对象,它类似于咱们JDK动态代理中的Proxy类,该类就是用来获取代理对象的 Enhancer enhancer = new Enhancer(); // 2. 设置父类的字节码对象。为啥子要这样做呢?因为使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的 enhancer.setSuperclass(obj.getClass()); // 3. 设置回调函数 enhancer.setCallback(this); // 4. 创建代理对象 return (T) enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if (method.getName().equals("makeCloth")){ System.out.println("制作服装前的准备........."); } Object invoke = method.invoke(obj, objects); if (method.getName().equals("makeCloth")){ System.out.println("对制作好的服装打包处理"); } return invoke; } }
最后就是测试类进行测试:
package com.hxk.pattern.proxy.cglib_proxy.lx; /** * @author *** * @create 2022-05-21 8:36 */ public class Client { public static void main(String[] args) { NaiKeCloth cloth = new NaiKeCloth(); NaiKeCloth proxy = new ProxyFactory<NaiKeCloth>(cloth).getProxy(); proxy.makeCloth("短袖"); String brand = proxy.brand(); System.out.println(brand); } }
我们来看一下运行结果:
最后,若是有接口,则你可以使用JDK动态代理(看我主页静态代理和动态代理)带来实现代理;若是没有接口,则你就可以使用CGLIB进行代理。