JDK动态代理CGLIB动态代理
Posted zqq_hello_world
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK动态代理CGLIB动态代理相关的知识,希望对你有一定的参考价值。
JDK动态代理
JDK动态代码是java.lang.reflect.*包提供的方式,它必须借助一个接口才能产出代理对象。
-
定义一个接口
/** * 定义接口,JDK动态代理必须借助一个接口才能产生代理对象 */ public interface HelloService { void sayHelloWorld(); }
-
创建接口实现类
/** * 实现类 */ public class HelloServerImpl implements HelloService { @Override public void sayHelloWorld() { System.out.println("线程:" + Thread.currentThread().getName() + " say Hello World"); } }
-
创建代理对象
JDK动态代理中,代理对象必须要实现代理逻辑必须实现 java.lang.reflect.InvocationHandler 接口,实现invoke()方法。
/** * 代理对象 * JDK动态代理中,要实现代理逻辑必须实现 java.lang.reflect.InvocationHandler 接口 */ public class JdkProxy implements InvocationHandler { /** * 真实对象 */ private Object target = null; /** * 绑定代理对象和真实对象的代理关系,并返回代理对象。这一步主要是代理对象和真实对象关系 * @param object * @return */ public Object bind(Object object){ this.target = object; //1.第一个参数是类加载器object.getClass(),这里采用的是object本身的类加载器 //2.第二个参数是动态代理对象下挂在哪些接口下。object.getClass().getInterfaces()这个方法是通过反射获取实现的接口,object是真实对象,也就是获取真实对象继承的接口 //3.第三个是传入代理类。代理类必须实现InvocationHandler接口,重写代理类逻辑方法invoke() return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); } /** * 代理方法逻辑处理方法 * @param proxy 代理对象,上面bind方法产生的对象 * @param method 当前调度方法 * @param args 方法参数 * @return 代理结果返回 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("进入代理逻辑方法===================="); System.out.println("在调用真实对象之前的逻辑输出 =。="); //调用真实对象的代理方法,这里相当于调用sayHelloWorld方法,看外部代理类调用哪个方法 Object object = method.invoke(target,args); System.out.println("在调用真实对象之后的输出 =_="); return object; } }
-
JDK动态代理调用测试
public class Test { /** * JDK动态代理测试 * @param args */ public static void main(String[] args) { //1.创建代理对象 JdkProxy jdkProxy = new JdkProxy(); //2.代理对象与真实对象绑定,因为挂在HelloService接口下,所以可以用HelloService去引用 HelloService helloService = (HelloService) jdkProxy.bind(new HelloServerImpl()); //3.helloService实际引用的是一个代理对象,会进入到代理对象的invoke方法。invoke里面调用真实对象的方法,前后加上自己的逻辑 helloService.sayHelloWorld(); } }
输出结果,在调用真实对象的方法前后执行了代理方法的逻辑
Connected to the target VM, address: '127.0.0.1:61305', transport: 'socket' 进入代理逻辑方法==================== 在调用真实对象之前的逻辑输出 =。= 线程:main say Hello World 在调用真实对象之后的输出 =_= Disconnected from the target VM, address: '127.0.0.1:61305', transport: 'socket'
CGLIB动态代理
JDK动态代理必须提供接口才能使用,在一些不能提供接口的环境中,只能采用其他第三方技术,比如CGLIB动态代理。它的优势在于不需要提供接口,只要一个非抽象类就能实现动态代理。
-
CGLIB是第三方实现,引入Jar包
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
-
创建一个类
/** * 创建cglib动态代理测试类,不需要实现接口 */ public class CglibImpl { /** * 创建一个测试方法,通过CGLIB动态代理调用此方法 */ public void sayHelloWorld(){ System.out.println("CGLIB,线程:" + Thread.currentThread().getName() + " say Hello World"); } }
-
创建CGLIB代理类
/** * 创建CGLIB动态代理的代理类,实现CGLIB的MethodInterceptor接口 */ public class CglibProxy implements MethodInterceptor{ /** * 生成CGLIB代理对象 * @param cls * @return */ public Object getProxy(Class cls){ //CGLIB Enhancer 增强类对象 Enhancer enhancer = new Enhancer(); //设置增强类 enhancer.setSuperclass(cls); //定义代理逻辑对象为当前对象,当前对象必须实现net.sf.cglib.proxy.MethodInterceptor接口 enhancer.setCallback(this); //生成并返回代理对象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("调用真实对象前==============="); //调用真实对象方法 Object result = methodProxy.invokeSuper(o,objects); System.out.println("调用真实对象后==============="); return result; } }
-
CGLIB代理测试
public class Test { public static void main(String[] args) { //创建cglib代理对象 CglibProxy cglibProxy = new CglibProxy(); //获取代理对象,getProxy()返回的是一个代理对象 CglibImpl cglibImpl = (CglibImpl) cglibProxy.getProxy(CglibImpl.class); //调用方法,走代理对象处理逻辑 cglibImpl.sayHelloWorld(); } }
输出结果
Connected to the target VM, address: '127.0.0.1:65050', transport: 'socket' 调用真实对象前=============== CGLIB,线程:main say Hello World 调用真实对象后=============== Disconnected from the target VM, address: '127.0.0.1:65050', transport: 'socket'
以上是关于JDK动态代理CGLIB动态代理的主要内容,如果未能解决你的问题,请参考以下文章