代理模式是一种结构型设计模式,它可以为其他对象提供一种代理以控制对这个对象的访问。
所谓的代理,是指具有与被代理对象相同的接口的类,客户端必须通过代理与被代理的目标类进行交互,而代理一般在交互的过程中(交互前后),进行某些特定的处理。
代理模式中的角色:
1.抽象对象角色
声明了目标类及代理类对象的共同接口,这样在任何可以使用目标对象的地方都可以使用代理对象。
2.目标对象角色
定义了代理对象所代表的目标对象。
3.代理对象角色
代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象和目标对象具有统一的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或者之后,执行某些操作,而非单纯的将调用传递给目标对象。
示例代码:
首先定义AbstractObject类,在其中定义代理类和目标类有公有的接口operation()
1 public abstract class AbstractObject{ 2 protected abstract void operation(); 3 }
目标实现类:
1 public class RealObject extends AbstractObject{ 2 3 @Override 4 protected void operation() { 5 System.out.println("do operation..."); 6 } 7 }
代理类:
1 package staticproxy; 2 3 public class ProxyObject extends AbstractObject{ 4 5 private RealObject realObject; 6 7 public ProxyObject(RealObject realObject) { 8 this.realObject=realObject; 9 } 10 11 @Override 12 protected void operation() { 13 System.out.println("do something before real peration..."); 14 if(realObject==null) { 15 realObject=new RealObject(); 16 } 17 realObject.operation(); 18 System.out.println("do something after real operation..."); 19 } 20 }
测试类:
1 package staticproxy; 2 3 public class ProxyTest { 4 5 public static void main(String[] args) { 6 AbstractObject proxy = new ProxyObject(new RealObject()); 7 proxy.operation(); 8 } 9 }
执行结果:
总结:
代理模式的使用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种方法:
(1)修改原有的方法来适应。
(2)采用一个代理类调用原来的方法,且对产生的结果进行控制。
使用代理模式可以将功能划分的更加清晰,有助于后期的维护。
以上所说的这种代理模式称为静态代理。
动态代理(也叫JDK代理)
jdk中的动态代理通过反射类Proxy和InvocationHandler回调接口实现,要求委托类必须实现一个接口,只能对该类接口中定义的方法实现代理,这在实际边中有一定的局限性。
见另一篇
Cglib代理
使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码。
https://www.cnblogs.com/chinajava/p/5880887.html----cglib动态代理解释
前提条件:
*需要引入cglib的jar文件,由于Spring的核心包中已经包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar
*目标类不能为final
*目标对象的方法如果为final/static,那么就不会拦截,即不会执行目标对象额外的业务方法
cglib的jar包---cglib-nodep-2.2.2.jar
目标对象,没有实现任何接口 Singer.java
1 package CglibProxy; 2 //目标对象,没有实现任何接口 3 public class Singer { 4 public void sing() { 5 System.out.println("唱一首歌"); 6 } 7 public void myname() { 8 System.out.println("我叫彭于晏"); 9 } 10 }
子类代理工厂--ProxyFactory.java
1 //Cglib子类代理工厂 2 public class ProxyFactory implements MethodInterceptor{ 3 4 //维护目标对象 5 private Object target; 6 //构造函数 7 public ProxyFactory(Object target) { 8 this.target=target; 9 } 10 11 //创建代理类对象 12 public Object getProxyInstance() { 13 //1.工具类 14 Enhancer en=new Enhancer(); 15 //2.设置父类 16 en.setSuperclass(target.getClass()); 17 //3.设置回调函数 18 en.setCallback(this); 19 //4.创建子类(代理对象) 20 return en.create(); 21 } 22 23 //重写的方法 拦截 24 @Override 25 public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { 26 System.out.println("向观众问好"); 27 //执行目标对象的方法 28 Object returnValue=arg1.invoke(target, arg2); 29 System.out.println("谢谢大家"); 30 return returnValue; 31 } 32 }
这里的代码也非常固定,只有标黄部分是需要自己写出
测试
1 package CglibProxy; 2 3 public class Test { 4 public static void main(String[] args) { 5 //目标对象 6 Singer target=new Singer(); 7 //代理对象 8 Singer proxy=(Singer)new ProxyFactory(target).getProxyInstance(); 9 //执行代理对象的方法 10 proxy.myname(); 11 proxy.sing(); 12 } 13 }