23种设计模式----------代理模式(三) 之 动态代理模式

(上一篇)种设计模式----------代理模式(二)

当然代理模式中,用的最广泛的,用的最多的是  动态代理模式。

动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理。

抽象接口的类图如下:

      --图来自设计模式之禅

所以动态代理模式要有一个InvocationHandler接口 和 GamePlayerIH实现类。其中 InvocationHandler是JD提供的动态代理接口,对被代理类的方法进行代理。

代码实现如下

抽象主题类或者接口:

 1 package com.yemaozi.proxy.dynamic;
 2
 3 /*
 4  * 动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理。
 5  */
 6 public interface IGamePlayer {
 7     //登录游戏
 8     public void login(String username, String password);
 9
10     //击杀Boss
11     public void killBoss();
12
13     //升级
14     public void upGrade();
15 }

需要被代理类:

 1 package com.yemaozi.proxy.dynamic;
 2
 3 public class GamePlayer implements IGamePlayer {
 4
 5     private String name = "";
 6
 7     public GamePlayer(String name){
 8         this.name = name;
 9     }
10
11     public void login(String username, String password) {
12         System.out.println("登录名为 "+username+" 进入游戏," + name + " 登录成功!");
13     }
14
15     public void killBoss() {
16         System.out.println(this.name + " 击杀了Boss!");
17     }
18
19     public void upGrade() {
20         System.out.println(this.name + "升级了!");
21     }
22
23 }

动态代理处理器类:

 1 package com.yemaozi.proxy.dynamic;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5
 6 public class GamePlayerInvocationHandler implements InvocationHandler{
 7
 8     //被代理的对象
 9     private Object obj;
10
11     //将需要代理的实例通过处理器类的构造方法传递给代理。
12     public GamePlayerInvocationHandler(Object obj){
13         this.obj = obj;
14     }
15
16     public Object invoke(Object proxy, Method method, Object[] args)
17             throws Throwable {
18         Object result = null;
19         if("login".equalsIgnoreCase(method.getName())){
20             //这个在主题方法不受任何影响的情况下,在主题方法前后添加新的功能,或者增强主题方法,
21             //从侧面切入从而达到扩展的效果的编程,就是面向切面编程(AOP Aspect Oriented Programming)。
22             //AOP并不是新技术,而是相对于面向对象编程的一种新的编程思想。在日志,事务,权限等方面使用较多。
23             System.out.println("代理登录游戏!");
24             result = method.invoke(this.obj, args);
25             return result;
26         }
27         result = method.invoke(this.obj, args);
28         return result;
29     }
30
31 }

由于代理是动态产生的,所以不需要再声明代理类。

动态代理场景类:

package com.yemaozi.proxy.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        IGamePlayer gp = new GamePlayer("张三");
        InvocationHandler gpHandler = new GamePlayerInvocationHandler(gp);
        //获取真实主题类的ClassLoader
        ClassLoader classLoader = gp.getClass().getClassLoader();
        //动态产生一个代理者。
        Class<?>[] cls = new Class[]{IGamePlayer.class};
        IGamePlayer proxyGp = (IGamePlayer) Proxy.newProxyInstance(classLoader, cls, gpHandler);
        proxyGp.login("zhangsan", "123456");
        proxyGp.killBoss();
        proxyGp.upGrade();
    }
}

执行结果:
代理登录游戏!
登录名为 zhangsan 进入游戏,张三 登录成功!
张三 击杀了Boss!
张三升级了!

//在此,我们没有创建代理类,但是确实有代理类帮我们完成事情。

其中,在此代理模式中,不仅代理是动态产生的(即在运行的时候生成),而且还在代理的时候,也增加了一些处理。在此处增加的处理,其实就是另一种编程思想-----面向切面编程思想(AOP Aspect Oriented Programming)。

带有AOP的动态代理模式类图:

        --图来自设计模式之禅

从上图中,可以看出有两个相对独立的模块(Subject和InvocationHandler)。动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。然而,通知Advice从另一个切面切入,最终在上层模块就是Client耦合,完成逻辑的封装。

代码清单如下

抽象主题或者接口:

1 package com.yemaozi.proxy.dynamic_aop;
2
3 public interface Subject {
4     public void doSomething(String str);
5     //...可以多个逻辑处理方法。。。
6 }

真实主题:

 1 package com.yemaozi.proxy.dynamic_aop;
 2
 3 public class RealSubject implements Subject{
 4
 5     public void doSomething(String str) {
 6         //do something...
 7         System.out.println("do something..." + str);
 8     }
 9
10 }

通知接口:

1 package com.yemaozi.proxy.dynamic_aop;
2
3 //通知接口及定义、
4 public interface IAdvice {
5     public void exec();
6 }

前置通知:

1 package com.yemaozi.proxy.dynamic_aop;
2
3 public class BeforeAdvice implements IAdvice {
4     //在被代理的方法前来执行,从而达到扩展功能。
5     public void exec() {
6         System.out.println("前置通知被执行!");
7     }
8 }

后置通知:

1 package com.yemaozi.proxy.dynamic_aop;
2
3 public class AfterAdvice implements IAdvice {
4
5     //在被代理的方法后来执行,从而达到扩展功能。
6     public void exec() {
7         System.out.println("后置通知被执行!");
8     }
9 }

动态代理的处理器类:

所有的方法通过invoke方法类实现。

 1 package com.yemaozi.proxy.dynamic_aop;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5
 6 public class MyInvocationHandler implements InvocationHandler {
 7
 8     //被代理的对象
 9     private Subject realSubject;
10     //通过MyInvocationHandler的构造方法将被代理对象传递过来。
11     public MyInvocationHandler(Subject realSubject){
12         this.realSubject = realSubject;
13     }
14     //执行被代理类的方法。
15     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
16         //在执行方法前,执行前置通知。
17         IAdvice beforeAdvice = new BeforeAdvice();
18         beforeAdvice.exec();
19         Object result = method.invoke(this.realSubject, args);
20         //在执行方法后,执行后置通知。
21         IAdvice afterAdvice = new AfterAdvice();
22         afterAdvice.exec();
23         //前置通知,和后置通知,都是要看具体实际的业务需求来进行添加。
24         return result;
25     }
26
27 }

动态代理类:

 1 package com.yemaozi.proxy.dynamic_aop;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5
 6 public class DynamicProxy {
 7
 8     /**
 9      * public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler handler)
10      * loader:
11      *             一个ClassLoader对象,定义了由哪个ClassLoader对象,来对生产的代理进行加载。
12      * interfaces:
13      *             一个Interfaces数组,表示我将要给我所代理的对象提供一组什么样的接口,
14      *             如果提供一组接口给它,那么该代理对象就宣称实现了该接口,从而可以调用接口中的方法。
15      *             即,查找出真是主题类的所实现的所有的接口。
16      * handler:
17      *             一个InvocationHandler对象,表示当我这个动态代理对象在调用方法时,会关联到该InvocationHandler对象。
18      *             该InvocationHandler与主题类有着关联。
19      */
20     public static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler handler){
21         @SuppressWarnings("unchecked")
22         T t = (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
23         return t;
24     }
25 }

从动态的产生动态代理类。

动态代理场景类:

 1 package com.yemaozi.proxy.dynamic_aop;
 2
 3 import java.lang.reflect.InvocationHandler;
 4
 5 public class AOPClient {
 6
 7     public static void main(String[] args) {
 8         Subject realSubject = new RealSubject();
 9         InvocationHandler handler = new MyInvocationHandler(realSubject);
10         ClassLoader classLoader = realSubject.getClass().getClassLoader();
11         Class<?>[] interfaces = realSubject.getClass().getInterfaces();
12         Subject proxySubect = DynamicProxy.newProxyInstance(classLoader, interfaces, handler);
13         proxySubect.doSomething("这是一个Dynamic AOP示例!!!");
14     }
15 }
16
17 执行结果:
18 前置通知被执行!
19 do something...这是一个Dynamic AOP示例!!!
20 后置通知被执行!

动态代理中invoke的动态调用:

动态代理类DynamicProxy是个纯粹的动态创建代理类通用类。

所以在具体业务中,可以在进一步封装具体的具有业务逻辑意义的DynamicProxy类。

代码如下

具体业务的动态代理:

 1 package com.yemaozi.proxy.dynamic_aop;
 2
 3 import java.lang.reflect.InvocationHandler;
 4 //具体业务的动态代理。
 5 public class SubjectDynamicProxy extends DynamicProxy {
 6     public static <T> T newProxyInstance(Subject subject){
 7         ClassLoader classLoader = subject.getClass().getClassLoader();
 8         Class<?>[] interfaces = subject.getClass().getInterfaces();
 9         InvocationHandler handler = new MyInvocationHandler(subject);
10         T t = newProxyInstance(classLoader, interfaces, handler);
11         return t;
12     }
13 }

动态代理在现在用的是非常的多的,如像Spring AOP ,DBCP连接池,AspectJ等。。。

时间: 2024-10-04 00:12:58

23种设计模式----------代理模式(三) 之 动态代理模式的相关文章

23种设计模式介绍(三)---- 行为型模式

由于设计模式篇幅比较大,如果在一篇文章讲完所有的设计模式的话不利于阅读.于是我把它分为三篇文章 23种设计模式介绍(一)---- 创建型模式 23种设计模式介绍(二)---- 结构型模式 23种设计模式介绍(三)---- 行为型模式 设计模式都是比较抽象的概念,所以大家一定要确保看懂类图,而后再自己写代码加强记忆. 概述 行为型模式一共有11种: 模板方法模式(Template Method) 策略模式(Strategy) 命令模式(Command) 中介者模式(Mediator) 观察者模式(

23种设计模式介绍(二)---- 结构型模式

由于设计模式篇幅比较大,如果在一篇文章讲完所有的设计模式的话不利于阅读.于是我把它分为三篇文章 23种设计模式介绍(一)---- 创建型模式 23种设计模式介绍(二)---- 结构型模式 23种设计模式介绍(三)---- 行为型模式 设计模式都是比较抽象的概念,所以大家一定要确保看懂类图而后再自己写代码加强记忆. 概述 结构型模式共七种: 适配器模式(Adapter) 外观模式(Facade) 桥接模式(Bridge) 装饰器模式(Decorator) 代理模式(Proxy) 享元模式(Flyw

23种设计模式介绍(一)---- 创建型模式

由于设计模式篇幅比较大,如果在一篇文章讲完所有的设计模式的话不利于阅读.于是我把它分为三篇文章 23种设计模式介绍(一)---- 创建型模式 23种设计模式介绍(二)---- 结构型模式 23种设计模式介绍(三)---- 行为型模式 由于设计模式都是比较抽象的概念,所以大家一定要确保看懂类图,而后再自己写代码加强记忆. 简介 设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接

23种设计模式(3):抽象工厂模式

定义:为创建一组相关或相互依赖的对象提供一个接口,并且无需指定他们的详细类. 类型:创建类模式 类图: 抽象工厂模式与工厂方法模式的差别 抽象工厂模式是工厂方法模式的升级版本号,他用来创建一组相关或者相互依赖的对象.他与工厂方法模式的差别就在于,工厂方法模式针对的是一个产品等级结构:而抽象工厂模式则是针对的多个产品等级结构.在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的全部产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类

23种设计模式(2):工厂方法模式

定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 类型:创建类模式 类图: 工厂方法模式代码 interface IProduct { public void productMethod(); } class Product implements IProduct { public void productMethod() { System.out.println("产品"); } } interface IFactory { publ

Java之23种设计模式解析(三)

C.关系模式(11 种)先来张图,看看这 11 中模式的关系:第一类:通过父类与子类的关系进行实现.第二类:两个类之间.第三类:类的状态.第四类:通过中间类 父类与子类关系13.策略模式(strategy)策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下: 图中 ICalculator 提供同意的方法,Ab

23种设计模式(7):中介者模式

定义 用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互. 类图 中介者结构 抽象中介者:定义好同事类对象到中介者对象的接口,用于各个同事类之间的通信.一般包括一个或几个抽象的事件方法,并由子类去实现. 中介者实现类:从抽象中介者继承而来,实现抽象中介者中定义的事件方法.从一个同事类接收消息,然后通过消息影响其他同时类. 同事类:如果一个对象会影响其他的对象,同时也会被其他对象影响,那么这两个对象称为同事类.在类图中,同事类

23种设计模式(11):责任链模式

定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式. 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }else if(i == 3){ Handler

Java的23种设计模式详解整理之创建型模式

最近重新阅读"四巨头"的设计模式. 对一些设计模式有了更多的理解. 原著中的例子是C++写的,不好理解. 这里我换成了Java, 代码示例仅供参考,没有具体实现. 介于个人水平有限,如有纰漏,请指正.有问题的朋友可以私信我或者发我邮箱(请到我主页查看),我看到就会回复. 希望和大家一起进步. 工作中有时候最困难的不是怎么去实现一个功能,而是怎么去设计一个功能.我常常会因为频繁改动需求大费脑筋.之后我在思考如何将一个功能在设计之初就做好扩展的准备,防止需求变动导致大面积的修改.code之