本文共 6767 字,大约阅读时间需要 22 分钟。
之前一直在接触动态代理,但是对于一些概念还是不能很好得理解,知道模板怎么用,但是换一种方式,我就懵逼了。
为什么会有动态代理呢,先看下面得例子:
package com.wx.proxy.jdkproxy;public interface Subject { void hello(String param); void say();}
package com.wx.proxy.jdkproxy;public class SubjectImpl implements Subject { public void hello(String param) { System.out.println("hello "+param); } public void say() { System.out.println("增加一个方法"); }}
package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Main { public static void main(String[] args) { Subject subject = new SubjectImpl(); subject.say(); }}
如果我想在这个方法前后打印日志,那么在不改动源码得基础上,创建一个代理类SubjectImplProxy,代码如下:
package jdkproxy;public class SubjectImplProxy implements Subject { private Subject subject= null; public SubjectImplProxy(Subject subject){ this.subject = subject; } @Override public int hello(String param) { System.out.println("开始执行hello方法"); subject.hello("world"); System.out.println("结束执行hello方法"); return 0; } @Override public void say() { System.out.println("开始执行say方法"); subject.say(); System.out.println("结束执行say方法"); }}
package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Main { public static void main(String[] args) { Subject subject = new SubjectImpl(); SubjectImplProxy subjectProxy = new SubjectImplProxy(subject); subjectProxy.say(); }}
这里功能虽然实现,但是有一个问题就是,如果出现SubjectImpl2,或者其他类型得类需要代理,都需要创建一个新的代理类,这样就会很麻烦,为了解决这个问题,就出现了动态代理
在此类中。当代理对象执行方法时,会执行invoke方法。通过反射得到method对象,然后执行方法,返回执行方法后的返回值
package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class SubjectProxy implements InvocationHandler{ private Subject subject; public SubjectProxy(Subject subject){ this.subject = subject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("-----------------begin--------------------"); Object invoke = method.invoke(subject,args); System.out.println("-----------------end----------------------"); return invoke; }}
package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main { public static void main(String[] args) { Subject subject = new SubjectImpl(); SubjectProxy subjectProxy = new SubjectProxy(subject); Subject proxy = (Subject)Proxy.newProxyInstance(subjectProxy.getClass().getClassLoader(), subject.getClass().getInterfaces(), subjectProxy); proxy.say(); }}
在此类中,通过匿名内部类创建代理对象,然后判断不同得执行方法,执行不同代码
package jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main { public static void main(String[] args) { Subject subject = new SubjectImpl(); SubjectProxy subjectProxy = new SubjectProxy(subject); Subject proxy = (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("say".equals(method.getName())){ System.out.println("=======开始========="); Object object = method.invoke(subject,args); System.out.println("=======结束========="); return object; } if("hello".equals(method.getName())){ System.out.println("=============begin==============="); Object object = method.invoke(subject,args); System.out.println("=============end================="); return object; } return null; } }); proxy.hello("world"); proxy.say(); }}
在jdk代理中,因为需要写实现类。为了直接对基本类进行代理,不要有实现接口,使用CGLIB动态代理。
package cglibProxy;public class CGLIB { public void sayHello(){ System.out.println("hello world"); } public void say(){ System.out.println("ceshi"); }}
创建代理类,实现MethodInterceptor接口
package cglibProxy;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class HelloInterceptor implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("begin time -----> "+ System.currentTimeMillis()); Object o1 = methodProxy.invokeSuper(o, objects); System.out.println("end time -----> "+ System.currentTimeMillis()); return o1; }}
package cglibProxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(CGLIB.class); enhancer.setCallback(new HelloInterceptor()); CGLIB cglib = (CGLIB) enhancer.create(); cglib.sayHello(); cglib.say(); }}
使用不需要实现MethodInterceptor接口得类,来代理普通类。使用method来判断,要对哪些方法进行代理。
package cglibProxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(CGLIB.class); //enhancer.setCallback(new HelloInterceptor()); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if("sayHello".equals(method.getName())){ System.out.println("begin time -----> "+ System.currentTimeMillis()); Object o1 = methodProxy.invokeSuper(o, objects); System.out.println("end time -----> "+ System.currentTimeMillis()); return o1; }else{ Object o2 = methodProxy.invokeSuper(o, objects); return o2; } } }); CGLIB cglib = (CGLIB) enhancer.create(); cglib.sayHello(); cglib.say(); }}
转载地址:http://eirdb.baihongyu.com/