代理模式
--什么是代理模式?
为其他对象提供一种代理,以控制这个对象的访问。说白了就是,在一些情况下,客户不想或者不能直接引用一个对象。而代理对象可以在客户和目标之间起到中介作用,去掉客户不能看到的内容和服务或者增加客户需要的额外服务。
--代理模式使用场景?
在对已有的方法进行使用的时候出现需要对原有方法进行修改,这时候:有两种选择。1.修改原有方法 2.使用一个第三者方法来调用原有的方法,并且对方法的产生的结果进行一定的控制。第一种明显违背了,对扩展开发,对修改关闭(开闭原则),而且在原来方法中修改可能使得原来类的功能变得模糊和多元化(就像现在企业多元化一样),而使用第二种方式,可以将功能划分的更加清晰,有助于后面的维护。所以在一定程度上,第二种方式是一个比较好的选择。当然,如果系统小的话,完全不用层层代理。反而显得臃肿。
--代理模式类比?
网上售票点 --黄牛 --你
你通过黄牛(代理角色)买票。黄牛其实也是在网上售票点(真实角色)买的票。黄牛作为代理角色,不仅会卖电影票,还会卖其他旅游景点的票。实现了增强。
--代理模式的角色?
抽象角色(Subject):声明真实对象和代理对象的共同接口;
代理角色(ProxySubject):代理角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象,相同的接口。以便任何时刻,都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他操作,相当于对于真实对象进行封装
真实角色(RealSubject):代理角色所代表的真实对象,是我们最终引用的对象
代理模式分类
--静态代理
静态代理就是程序运行前就已经存在的代理类字节码文件,代理类和委托类关系在运行前就确定了。
/** * 抽象角色,真实对象和代理对象的接口 * * @author LiJie * @create 2018/1/18 16:39 */ public interface Subject { /** * 让我们来做些事 */ void doSomeThing(); }
/** * 真实角色:代理角色所代表的真实对象 * * @author LiJie * @create 2018/1/18 16:42 */ public class RealSubject implements Subject { @Override public void doSomeThing() { System.out.println("我是真实角色"); } }
/** * 代理角色:替真实角色出头的 * * @author LiJie * @create 2018/1/18 16:40 */ public class ProxySubject implements Subject { //目标对象引用 private Subject subject; public ProxySubject(Subject subject) { this.subject = subject; } @Override public void doSomeThing() { System.out.println("我是代理角色"); subject.doSomeThing(); } /** * 除了代理真实角色,做事。还可以做些私活 */ public void doAnotherThing() { System.out.println("我是代理角色,还可以挣些外快"); } }
/** * 测试类 * * @author LiJie * @create 2018/1/18 16:49 */ public class TestSubject { public static void main(String []args) { //真实角色引用 Subject subject = new RealSubject(); ProxySubject proxySubject = new ProxySubject(subject); proxySubject.doSomeThing(); //封装真实角色,扩展方法。 proxySubject.doAnotherThing(); } }
--动态代理
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
Proxy.newProxyIntance().方法说明。
参数1:类加载器(这个参数可去掉)
参数2:代理的接口(可以选择性代理接口)
参数3:InvocationHandler的实现类。该接口解开类与拦截类之间的耦合
/** * 代理工厂类 * * @author LiJie * @create 2018/1/18 17:16 */ public class ProxyFactory { //维护一个目标对象 private Object subject; public ProxyFactory(Object subject) { this.subject = subject; } /** *给目标对象生成代理对象 */ public Object getProxyInstance() { return Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //执行目标对象方法 Object returnObject = method.invoke(subject,args); return returnObject; } } ); } }
public class TestDynamicSubject { public static void main(String[] args) { //真实对象引用 Subject subject = new RealSubject(); //通过代理对象工厂类,获得该目标对象的代理对象引用 Subject proxySubject = (Subject) new ProxyFactory(subject).getProxyInstance(); proxySubject.doSomeThing(); } }jdk提供的动态代理类。必须要有接口。jdk代理类是这样一种Class:它在运行时生成Class,在生成它时,你必须提供一组interface给他。然后该Class就宣称实现了这些Interface。
Cglib代理
假如类没有接口,单单一个对象,可以使用Cglib代理。
Cglib代理也叫子类代理。他是在内存中构建一个子类对象。从而实现对目标功能的扩展
广泛被许多aop框架使用,为他们的方法提供拦截
Cglib子类代理实现方法
1.引入jar包。spring-core.jar
2.代理的类不能为final/static.否则将不会拦截到
/** * (没有接口)真实对象 * * @author LiJie * @create 2018/1/19 15:29 */ public class Subject { public void doSomething() { System.out.println("我是真实角色"); } }
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * Cglib代理工厂类。在内存中动态构建一个子类对象 * * @author LiJie * @create 2018/1/19 15:31 */ public class ProxyFactory implements MethodInterceptor { //需要维护的对象 private Object subject; public ProxyFactory(Object subject) { this.subject = subject; }
/** * set好之后,就可以创建代理对象 * @return */ public Object getProxyInstance() { //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(subject.getClass()); //3.设置回调函数 en.setCallback(this); //创建子类代理对象 return en.create(); }
/** * 测试类 * * @author LiJie * @create 2018/1/19 15:40 */ public class Test { public static void main(String []args){ Subject subject = new Subject(); Subject proxySubject = (Subject)new ProxyFactory(subject).getProxyInstance(); proxySubject.doSomething(); } }文中代码:http://www.cnblogs.com/cenyu/p/6289209.html