1静态代理
首先先看不使用代理
public class Man implements Action { private String name; public Man(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void sayHello() { System.out.println(this.name + " say hello"); } @Override public void eat(String food) { System.out.println("eat " + food); } }
public interface Action { void sayHello(); void eat(String food); }
public class Man implements Action { private String name; public Man(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void sayHello() { System.out.println(this.name + " say hello"); } }
public interface Action { void sayHello()
public static void main(String[] args) { Man man = new Man("jj"); man.sayHello(); }
上面是一个不使用静态代理的普通代码,但当我们想对sayHello方法增强其的功能时,比如增加一个openMouth行为时就不得不修改sayhello的代码逻辑,这不符合设计原则,所以我们可以使用代理模式进行代码修改。
public class StaticProxy implements Action { private Man man; public StaticProxy(Man man) { super(); this.man = man; } @Override public void sayHello() { // TODO Auto-generated method stub openMouth(); man.sayHello(); } private void openMouth() { System.out.println(man.getName() + "open mouth"); } }
public static void main(String[] args) { Man man = new Man("jj"); StaticProxy sp = new StaticProxy(man); sp.sayHello(); }
这样我们通过代理对象实现man对象的sayhello方法的增强后功能。这样的好处是,假如是Man每个方法都要增加日志功能,不可能在每个方法中加入log方法,我们可以在代理类的实现方法中调用Man的对应方法,后面再增加log逻辑。实现解耦合。
我们可以总结一下静态代理 1.代理类和被代理类都要实现相同的接口(代理类要对被代理类进行功能增强的,不实现相同的接口,代理类就不知道增强什么功能) 2.代理类需要持有被代理类实例对象(功能增强是代理类和被代理类共同协作的结果)3.代理类进行实际的行为
2.jdk动态代理
public class DynamicProxyHandller implements InvocationHandler { private Object proxyed; public Object getProxyed() { return this.proxyed; } public void setProxyed(Object proxyed) { this.proxyed = proxyed; } // 获取代理实例 public Object getProxyInstance() { return Proxy.newProxyInstance(proxyed.getClass().getClassLoader(), proxyed.getClass().getInterfaces(), this); } public DynamicProxyHandller(Object proxyed) { super(); this.proxyed = proxyed; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { dosomeBefore(); method.invoke(proxyed, args); return null; } public void dosomeBefore() throws Exception { Field field = proxyed.getClass().getDeclaredField("name"); field.setAccessible(true); System.out.println((String) field.get(proxyed) + " dosomeBefore"); } }
public static void main(String[] args) { Action man = new Man("jj"); DynamicProxyHandller dp = new DynamicProxyHandller(man); Action ac = (Action) dp.getProxyInstance(); ac.sayHello(); ac.eat("apple"); }
jj dosomeBefore
jj say hello
jj dosomeBefore
jj eat apple
从测试类中看出,我们先实例一个包含被代理类对象的动态代理handler(实现了InvocationHandler接口),然后通过handler实例一个代理对象,再通过代理对象去做相应的行为。这样整个动态代理就这样完成。
那么这样的好处又是什么?
首先静态代理和动态代理的区别很明显,静态代理有实际的代理类还需实现接口,动态代理只有一个handler,通过handler去实例一个代理对象。
然后假如Action接口里面有很多方法,静态代理类需要实现这些方法,然而我仅仅就想给每个方法加个日志而已。动态代理就很好的解决了这个问题
3.cglib动态代理
JDK动态代理中被代理的类必须实现接口,假如被代理类没有实现接口,我们不能强行的给它增加接口,那么cglib动态代理就可以解决这个问题
public class User { public void eat(String food) { System.out.println("eat " + food); } }
public class UserInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // TODO Auto-generated method stub System.out.println("预处理"); return proxy.invokeSuper(obj, args); } }
public static void main(String[] args) { Enhancer enchancer = new Enhancer();// 字节码增强器 enchancer.setSuperclass(User.class);// 设置被代理类为父类 enchancer.setCallback(new UserInterceptor());// 设置回调 User user = (User) enchancer.create();// 创建代理实例 user.eat("葡萄"); }