电影是电影公司委托给影院进行播放的,但是影院可以在播放电影的时候,产生一些自己的经济收益,比如卖爆米花、可乐等,然后在影片开始结束时播放一些广告。
现在用代码来进行模拟。
首先写一个接口,有播放电影的功能
public interface Movie {
void play(); }
然后,创建一个真正实现Movie接口的类
public class RealMovie implements Movie { @Override public void play() { // TODO Auto-generated method stub System.out.println("您正在观看电影 《肖申克的救赎》"); } }
写一个代理类(电影院),除了有播放电影的功能外,还有其他附加功能
Cinema 就是 Proxy 代理对象,它有一个 play() 方法。不过调用 play() 方法时,它进行了一些相关利益的处理,那就是广告。
public class Cinema implements Movie { 4 5 RealMovie movie; 6 7 public Cinema(RealMovie movie) { 8 super(); 9 this.movie = movie; 10 } 11 12 13 @Override 14 public void play() { 15 16 guanggao(true); 17 18 movie.play(); 19 20 guanggao(false); 21 } 22 23 public void guanggao(boolean isStart){ 24 if ( isStart ) { 25 System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!"); 26 } else { 27 System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!"); 28 } 29 } 30 31 }
测试代码
public class ProxyTest { public static void main(String[] args) { RealMovie realmovie = new RealMovie(); Movie movie = new Cinema(realmovie); movie.play(); } }
与静态代理的功能与目的是没有区别的,区别在于:
上一节代码中 Cinema 类是代理,我们需要手动编写代码让 Cinema 实现 Movie 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 Movie 接口的代理,而不需要去定义 Cinema 这个类。这就是它被称为动态的原因。
动态代理的例子:
假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒。我们进行代码的模拟。
1.创建一个卖酒的接口
public interface SellWine { void mainJiu(); }
2.创建一个茅台酒的类
public class MaotaiJiu implements SellWine { @Override public void mainJiu() { // TODO Auto-generated method stub System.out.println("我卖得是茅台酒。"); } }
3.还需要一个柜台来卖酒(InvocationHandler )
public class GuitaiA implements InvocationHandler { private Object pingpai; public GuitaiA(Object pingpai) { this.pingpai = pingpai; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("销售开始 柜台是: "+this.getClass().getSimpleName()); method.invoke(pingpai, args); System.out.println("销售结束"); return null; } }
4.测试
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub MaotaiJiu maotaijiu = new MaotaiJiu(); //实际的对象 InvocationHandler jingxiao1 = new GuitaiA(maotaijiu); //创建一个InvocationHandler对象 SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(), MaotaiJiu.class.getInterfaces(), jingxiao1); //动态生成代理对象 dynamicProxy.mainJiu(); //通过代理对象调用卖酒方法 } }
通过 Proxy 的静态方法 newProxyInstance 可以动态创建代理。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
InvocationHandler 内部只是一个 invoke() 方法,正是这个方法决定了怎么样处理代理传递过来的方法调用。
因为,Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。
具体实现可参考源码
在不修改被代理对象的源码上,进行功能的增强,这在 AOP 面向切面编程领域经常见。
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,
从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等。
转载来自:https://blog.csdn.net/briblue/article/details/73928350
原文:https://www.cnblogs.com/karinemo/p/13019574.html