在上一篇博客中简单写了一下静态代理,这里主要讲一下动态代理
动态代理主要有两种
JDK动态代理 CGLIB动态代理
那这两种代理有什么区别呢?
(根据自己的理解总结)
1.JDK动态代理
他的特点是:目标对象必须有接口
他的实质是:创建了接口的一个实现类
他运行的时机:程序运行时
2.CGLIB动态代理
他的特点是:在一个类型没有接口的情况下进行代理
他的实质是:在内存中构建目标类型的子类
他运行的时机是:编译时
简单介绍完这两种代理后,就用个例子具体看怎么实现动态代理
先做JDK动态代理
准备一个接口ISomeService,接口中有一个方法doSome(),和一个这个接口的实现类SomeServiceImpl,并重写其中的方法,具体代码如下
package demo15; /** * Created by mycom on 2018/3/8. */ public interface ISomeService { public void doSome(); }
package demo15; /** * Created by mycom on 2018/3/8. */ public class SomeServiceImpl implements ISomeService { public void doSome() { System.out.println("十点十分的复习"); } }
使用JDK动态代理不需要再配置文件中进行配置,所以现在直接进行测试,但是测试的时候不能使用单测,而是使用main方法进行测试
package demo15; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Created by mycom on 2018/3/8. */ public class Test { public static void main(String[] args) { //首先创建一个接口的实现类 final SomeServiceImpl service=new SomeServiceImpl(); //在调用方法之前想使用动态代理记录一下日志,生成动态代理,返回的是接口 ISomeService proxyInstance =(ISomeService) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler() { /** * * @param proxy 代理对象 * @param method 目标类型的方法 * @param args 方法的参数 * @return * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在这里记录一下日志 System.out.println("before====="); //调用method 的 method.invoke(service,args);//相当于执行目标类型的方法 System.out.println("after======="); return null; } }); //调用动态代理中的方法中的方法 proxyInstance.doSome(); } }
运行的结果如下
这说明运行时先执行了invoke方法,再执行接口中doSome的方法,实验成功!
使用CGLIB动态代理实现上述中的运行结果,如何实现呢?
这时就不用再创建接口了,(在这里我就使用上面的SomeServiceImpl这个类了,这个类中不用做改动),我直接进行测试了,测试还和上面一样,使用main方法测试,不用配置文件
package demo09; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * Created by mycom on 2018/3/8. */ public class Test { public static void main(String[] args) { final SomeServiceImpl service=new SomeServiceImpl(); Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(service.getClass()); enhancer.setCallback(new MethodInterceptor() { /** * * @param o 代理对象 * @param method 目标类型的方法 * @param objects 目标方法的参数 * @param methodProxy 代理类的方法 是一个新的参数 * @return * @throws Throwable */ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before====="); methodProxy.invoke(service,objects); System.out.println("after====="); return null; } }); SomeServiceImpl proxy =(SomeServiceImpl) enhancer.create(); proxy.doSome(); } }
运行结果和上面的一样,这就是两种方法实现动态代理!