代理模式

来源:互联网 发布:c语言void的用法 编辑:程序博客网 时间:2024/04/29 20:57

2 定义
为其他对象提供一种代理以控制对这个对象的访问。
代理类模板:

public class Proxy implements Subject {    //要代理哪个实现类    private Subject subject = null;    //默认被代理者    public Proxy(){        this.subject = new Proxy();    }    //通过构造函数传递代理者    public Proxy(Object... objects) {    }    //实现接口中定义的方法    public void request() {        this.before();        this.subject.request();        this.after();    }    //预处理    private void before(){        //do something    }    //善后处理    private void after(){        //do something    }}

3 运用
1) 优点
2) 使用场景
Spring AOP就是动态代理典型的例子。

4 扩展
1) 普通代理
要知道代理的存在,才能访问
2) 强制代理
直接调用真实角色,其代理的产生是有真实角色决定的。
3) 代理是有个性的
意思就是说会做一些代理自己想做的事。
4) 动态代理
动态代理是在实现阶段不同关心代理谁,而在运行阶段才指定代理哪一个对象。
动态代理的主要意图就是解决我们常说的“审计”问题,也就是横切面编程,在不改变我们已有代码结构的情况下增强或控制对象的行为。日志、事务、权限。
动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的互相耦合的关系。
静态代理和动态代理的区别

package dongtaidaili;//抽象主题public interface Subject {    //业务操作    public void doSomething(String str);}
package dongtaidaili;//真实主题public class RealSubject implements Subject {    @Override    public void doSomething(String str) {            System.out.println("do somethingd----------->" + str);    }}
package dongtaidaili;//通知接口public interface IAdvice {    //通知只有一个方法,执行即可    public void exec();}
package dongtaidaili;public class BeforeAdvice implements IAdvice {    @Override    public void exec() {        System.out.println("我是前置通知,我被执行了");    }}
package dongtaidaili;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;//动态代理的Handler类public class MyInvocationHandler implements InvocationHandler {    //被代理的对象    private Object target;    //通过构造函数传递一个对象    public MyInvocationHandler(Object object) {        this.target = object;    }    //代理方法    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        return method.invoke(this.target, args);    }}
package dongtaidaili;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;//动态代理类public class DynamicProxy<T> {    public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces,            InvocationHandler h){        //寻找连接点,AOP框架使用元数据定义        if(true) {            //执行一个前置通知            (new BeforeAdvice()).exec();        }        //执行目标,并返回结果        //h的实现类实现interfaces的所有方法,由其invoke方法接管所有方法的实现        return (T)Proxy.newProxyInstance(loader, interfaces, h);    }}
package dongtaidaili;import java.lang.reflect.InvocationHandler;public class Client {    public static void main(String[] args) {        //定义一个主题        Subject subject = new RealSubject();        //定义一个Handler        InvocationHandler handler = new MyInvocationHandler(subject);        //定义主题的代理        Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),                subject.getClass().getInterfaces(), handler);        //代理的行为        proxy.doSomething("Finish");    }}
package dongtaidaili;import java.lang.reflect.InvocationHandler;public class SubjectDynamicProxy extends DynamicProxy {    public static <T> T newProxyInstance(Subject subject) {        //获得ClassLoader        ClassLoader loader = subject.getClass().getClassLoader();        //获得接口数组        Class<?>[] classes = subject.getClass().getInterfaces();        //获得handler        InvocationHandler handler = new MyInvocationHandler(subject);        return newProxyInstance(loader, classes, handler);    }}
package dongtaidaili;public class Client2 {    public static void main(String[] args) {        Subject subject = new RealSubject();        Subject proxy = SubjectDynamicProxy.newProxyInstance(subject);        proxy.doSomething("Finish!");    }}

添加一个要代理的接口:

package dongtaidaili;public interface Subject2 {    public void doElseSomething(String str);}
package dongtaidaili;public class RealSubject2 implements Subject2 {    @Override    public void doElseSomething(String str) {        System.out.println("do else something!" + str);    }}

代理类完成不用修改:

package dongtaidaili;import java.lang.reflect.InvocationHandler;public class Client {    public static void main(String[] args) {        //定义一个主题        Subject subject = new RealSubject();        //定义一个Handler        InvocationHandler handler = new MyInvocationHandler(subject);        //定义主题的代理        Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),                subject.getClass().getInterfaces(), handler);        //代理的行为        proxy.doSomething("Finish");        System.out.println("----------------动态代理比静态代理的优点----------------------");        Subject2 subject2 = new RealSubject2();        InvocationHandler handler2 = new MyInvocationHandler(subject2);        Subject2 proxy2 = SubjectDynamicProxy.newProxyInstance(subject2.getClass().getClassLoader(),                subject2.getClass().getInterfaces(),handler2);        proxy2.doElseSomething("else Finish");    }}

5)静态代理
两个接口要写两个代理类

package dongtaidaili;public class SubjectProxy implements Subject {    private Subject subject;    public SubjectProxy(Subject subject) {        super();        this.subject = subject;    }    @Override    public void doSomething(String str) {        System.out.println("前置通知,我被执行了");        this.subject.doSomething(str);    }}
package dongtaidaili;public class Subject2Proxy implements Subject2 {    private Subject2 subject2;    public Subject2Proxy(Subject2 subject2) {        super();        this.subject2 = subject2;    }    @Override    public void doElseSomething(String str) {        System.out.println("前置通知,我被执行了");        this.subject2.doElseSomething(str);    }}
package dongtaidaili;public class SubjectProxyClient {    public static void main(String[] args) {        Subject subject = new RealSubject();        Subject proxy = new SubjectProxy(subject);        proxy.doSomething("Finish");        System.out.println("-------静态代理的缺点,一个代理只服务于一个接口,会造成冗余代码------------");        Subject2 subjec2 = new RealSubject2();        Subject2 proxy2 = new Subject2Proxy(subjec2);        proxy2.doElseSomething("else Finish");    }}

或者这样:

package dongtaidaili;public class Subject1_2Proxy implements Subject, Subject2 {    private Subject subject;    private Subject2 subject2;    public Subject1_2Proxy(Subject subject, Subject2 subject2) {        super();        this.subject = subject;        this.subject2 = subject2;    }    @Override    public void doElseSomething(String str) {        System.out.println("前置通知,我被执行了");        this.subject2.doElseSomething(str);    }    @Override    public void doSomething(String str) {        System.out.println("前置通知,我被执行了");        this.subject.doSomething(str);    }}
package dongtaidaili;public class SubjectProxyClient {    public static void main(String[] args) {        Subject subject = new RealSubject();        Subject proxy = new SubjectProxy(subject);        proxy.doSomething("Finish");        System.out.println("-------静态代理的缺点,一个代理只服务于一个接口,会造成冗余代码------------");        Subject2 subjec2 = new RealSubject2();        Subject2 proxy2 = new Subject2Proxy(subjec2);        proxy2.doElseSomething("else Finish");        System.out.println("-------------------------");        Subject proxy_1 = new Subject1_2Proxy(subject, null);        proxy_1.doSomething("Hello world");        Subject2 proxy_2 = new Subject1_2Proxy(null, subjec2);        proxy_2.doElseSomething("else Hello world");    }}

6)静态代理和动态代理优缺点
*代理的共同优点:
业务类只需要关注业务逻辑本身。
*静态代理缺点:
代理对象的一个接口只服务于一种类型的对象,如果代理的方法很多,要为每一个方法都进行代理。
* 动态代理的缺点
只有实现了某个接口的类才可以使用Java动态代理机制。但是有cglib(Code生成类库),可以在运行期扩展Java类与实现Java接口。

5 最佳实现
AOP

0 0
原创粉丝点击