2019独角兽企业重金招聘Python工程师标准>>>
最简单的是静态代理方法,即代理模式,这里就不多啰嗦了。。
重点说一下JDK的动态代理和Cglib的动态代理吧
先说JDK的,需要被代理的类需要有接口,否则无法实现
package proxy.dynamic;public interface IBook {void add();
}
实现接口的类如下
package proxy.dynamic;public class Book implements IBook {@Overridepublic void add() {System.out.println("Add Method!");}}
创建一个代理类,需要实现一个接口InvocationHandler接口,里面有一个invoke方法需要实现
同时创建一个生成实例的方法
package proxy.dynamic;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class BookProxy implements InvocationHandler{private Object target;public Object bind(Object target) {this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);//这里需要接口}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object result=null;System.out.println("Before");result=method.invoke(target, args);//执行方法System.out.println("After");return result;}}
接下来创建测试类
package proxy.dynamic;public class Test {/*** @param args*/public static void main(String[] args) {BookProxy bp = new BookProxy();IBook book = (IBook) bp.bind(new Book());book.add();}}
可以看到依次输出了Before,方法,After
下面说一下Cglib的代理,Cglib代理不需要原类实现接口,依赖Cglib和asm两个Jar包
需要代理的类如下
package cglib.proxy;public class Book {public void add() {System.out.println("Add Method!");}
}
创建一个代理类,实现MethodInterceptor接口,同时写一个生成实例的getInstance方法
package cglib.proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor{private Object target;public Object getInstance(Object target){this.target=target;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.target.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {System.out.println("Before");proxy.invokeSuper(obj, args);System.out.println("After");return null;}}
接下来就是简单测试一下
package cglib.proxy;public class Test {/*** @param args*/public static void main(String[] args) {CglibProxy proxy = new CglibProxy();Book book=(Book) proxy.getInstance(new Book());book.add();}}
运行效果一样的
简单总结一下,JDK动态代理,需要实现一个接口InvocationHandler,要求被代理的对象必须有一个接口
Cglib代理需要实现MethodInterceptor接口,不需要被代理的类必须有接口
性能方法,参考其他文章,说JDK代理适合多例模式,而单例模式Cglib更好一些,因为Cglib是用底层的字节码技术生成实例,耗费时间较长,性能不如JDK动态代理。(有待验证。。)