目录
- 动态代理
动静代理
- JDK动静代理
- cglib动静代理
动态代理
被代理类和代理类都实现Apple接口
public interface Apple { Integer buyApple();}
创立一个“烟台”苹果的实例作为被代理类,外面次要实现一个购买苹果的办法,也是前面次要用来被代理加强的办法。
public class YanTaiApple implements Apple{ private Integer price; public YanTaiApple(Integer price) { this.price = price; } @Override public Integer buyApple(){ return this.price; }}
创立一个“烟台”苹果的代理类,其次要充当中间商的角色,次要的加强就是价格更高。
public class YanTaiAppleProxy implements Apple{ private Apple apple; public YanTaiAppleProxy(Apple apple) { this.apple = apple; } @Override public Integer buyApple() { Integer price = apple.buyApple()+2; System.out.println("苹果收购价格"+apple.buyApple()+"元,出售价"+price+"元"); return price; }}
上面再办法中,咱们通过代理商去买苹果......
public class StaticProxyTest { @Test public void test(){ Apple apple = new YanTaiAppleProxy(new YanTaiApple(3)); apple.buyApple(); }}======后果======苹果收购价格3元,出售价5元
动静代理
仔细分析下面的动态代理,咱们会发现,对每个类进行代理,都要创立不同的代理类,如果像当初有河南苹果、新疆苹果、昭通苹果....那么咱们须要为每种苹果都创立一个代理类,难道咱们不能够应用一个代理商代理多种苹果吗?显然动态代理是有很大局限性的。
动静代理是通过反射的形式能够动态创建原始类的代理类,而后在零碎种用代理类替换掉原始类,在java语言种动静代理次要是通过反射机制来实现的。
JDK动静代理
jdk动静代理次要是基于接口和java反射包中的Proxy类实现的,也就是被代理类和代理类实现雷同的接口,而后通过Proxy代理接口进行动静扩大(emm....次要看上面的实现)。
接口和原始类咱们都持续应用下面的Apple和YanTaiApple,而后代理类实现如下,咱们须要实现接口InvocationHandler而后在invoke办法中对办法调用进行加强(代理商的价格减少两元),当原始类关联这个代理类后,执行接口的办法会主动进入invoke这个办法进行加强。
public class AppleProxyHandler implements InvocationHandler { private Apple apple; public AppleProxyHandler(Apple apple) { this.apple = apple; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //获取price字段 Field field = apple.getClass().getDeclaredField("price"); //放开权限 - 针对private field.setAccessible(true); Integer price = (Integer) field.get(apple); //从新设置值 field.set(apple,price+2); return method.invoke(apple,args); }}
通过Proxy关联YanTaiApple和AppleProxyHandler实例,当然AppleProxyHandler的结构参数中不仅能够传入YanTaiApple实例,也可传入其余实现Apple接口的类的实例,也就是说AppleProxyHandler能够代理所有Apple接口的实现类。
public class JdkProxyTest { @Test public void test(){ //关联 Apple apple = (Apple) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Apple.class}, new AppleProxyHandler(new YanTaiApple(2))); System.out.println(apple.buyApple()); }}=====后果=====4
认真思考下面的设计是略微有些不合理的,因为Apple接口中可能不只是有buyApple办法也可能有其它办法,那么咱们代理类明想代理的是由buyApple办法,那么能够做上面优化 。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("buyApple".equals(method.getName())) { //获取price字段 Field field = apple.getClass().getDeclaredField("price"); //放开权限 - 针对private field.setAccessible(true); Integer price = (Integer) field.get(apple); //从新设置值 field.set(apple, price + 2); } return method.invoke(apple,args);}
cglib动静代理
cglib代理和jdk代理的次要区别是,jdk动静代理只反对接口代理不反对类代理,Proxy.newProxyInstance
的第二参数只能传入接口的类对象汇合,如果传入类的话会报java.lang.IllegalArgumentException: java.lang.Object is not an interface
异样。而cglib是通过继承的形式来实现动静代理,会在运行的时候动静生成被代理类的一个子类对象,因而如果这个类被final润饰的话是无奈被cglib代理的。
上面持续应用苹果的实例,然而应用cglib动静代理,咱们就不须要对立的接口类了。
public class YanTaiApple { public Integer price; public YanTaiApple(Integer price) { this.price = price; } public Integer buyApple(){ return this.price; }}
代理类是通过实现MethodInterceptor接口,而后在intercept办法实现代理逻辑的
public class AppleProxy implements MethodInterceptor { @Override public Object intercept(Object apple, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //apple是动静生成YanTaiApple的一个子类 Field field = apple.getClass().getSuperclass().getDeclaredField("price"); field.setAccessible(true); Integer price = (Integer) field.get(apple); field.set(apple,price+2); return methodProxy.invokeSuper(apple,objects); }}
测试类须要应用Enhancer类将被代理类设置为SuperClass,代理类设置为Callback
public class CglibProxyTest { @Test public void test(){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(YanTaiApple.class); enhancer.setCallback(new AppleProxy()); //参数类型、参数值 - create相当于构造函数 YanTaiApple yanTaiApple = (YanTaiApple) enhancer.create(new Class[]{Integer.class}, new Integer[]{3}); System.out.println(yanTaiApple.buyApple()); }}=====后果=====5