代理模式与动态代理、AOP

代理设计模式的原理:

使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

静态代理
  • 特点:

  • 代理类结合被代理类在编译期间,就确定下来了

静态代理举例:

package com.test.proxy;
 
/**
 * CLassName: StaticProxyTest
 * Package: com.test.proxy
 * Description:
 *              静态代理举例
 *              特点:代理类结合被代理类在编译期间,就确定下来了
 *
 * @Author: JOKER-wqc
 * @Version: v1.0
 */
/*
 */
interface ClothFactory{
    void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
 
    private ClothFactory clothFactory;//用被代理类对象进行实例化
 
    public ProxyClothFactory(ClothFactory clothFactory) {
        this.clothFactory = clothFactory;
    }
 
    @Override
    public void produceCloth() {
        System.out.println("生产衣服前的准备工作");
 
        clothFactory.produceCloth();
 
        System.out.println("生产衣服后的收尾工作");
    }
}
//被代理类
class NikeClothFactory implements ClothFactory{
 
    @Override
    public void produceCloth() {
        System.out.println("生产Nike的衣服");
    }
}
 
public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类的对象
        NikeClothFactory nike = new NikeClothFactory();
        //创建代理类的对象
        ProxyClothFactory proxyclothfactory =  new ProxyClothFactory(nike);
        proxyclothfactory.produceCloth();
 
    }
 
 
}
静态代理的缺点

因为静态代理在代码运行之前就已经存在代理类了,所以每一个代理对象都需要去建一个代理类去代理,当需要代理的对象有很多时,就需要创建很多的代理类,降低了程序可维护性。

动态代理

是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。

动态代理使用场合:
  • 调试

  • 远程方法调用

动态代理的优点:

抽象角色中(接口)声明的所有方法都被转移到调用处理器个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。

动态代理举例:

package com.test.proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
 * CLassName: DynamicProxyTest
 * Package: com.test.proxy
 * Description:
 *             动态代理的举例
 * @Author: JOKER-wqc
 * @Version: v1.0
 */
interface Human{
    String getBelief();
 
    void set(String food);
}
//被代理类
class SuperMan implements Human{
 
    @Override
    public String getBelief() {
        return "超人的信仰!";
    }
 
    @Override
    public void set(String food) {
        System.out.println("我喜欢吃"+food);
    }
}
 
class ProxyFactory{
    //调用此方法:返回一个代理类的对象
    public static Object getInstance(Object c){
        myInvocationHandler myInvocationHandler = new myInvocationHandler();
        myInvocationHandler.bind(c);
        return Proxy.newProxyInstance(c.getClass().getClassLoader(),c.getClass().getInterfaces(),myInvocationHandler);
    }
 
}
 
class myInvocationHandler implements InvocationHandler{
 
    private Object obj;//需要使用被代理类的对象进行赋值
 
    public void bind(Object obj){
        this.obj = obj;
    }
    //当我们通过代理类的对象,调用方法时,就会自动的调用如下方法invoke()
    //讲被代理类要执行的方法的功能声明在invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        //obj:被代理类对象
        return method.invoke(obj,args);//如原方法有返回值则本方法也可返回
    }
}
 
public class DynamicProxyTest {
 
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //生成代理类对象
        Human proxyHuman = (Human) ProxyFactory.getInstance(superMan);
        //通过代理类自动调用被代理类中的同名方法
        System.out.println(proxyHuman.getBelief());
        proxyHuman.set("钢铁");
 
        System.out.println("--------------------------------------");
 
        NikeClothFactory nike = new NikeClothFactory();
 
        ClothFactory proxyNike = (ClothFactory) ProxyFactory.getInstance(nike);
        proxyNike.produceCloth();
 
    }
 
 
}

AOP与动态代理的举例

动态代理与AOP (Aspect Orient Programming)

上面介绍的Proxy和InvocationHandler,很难看出这种动态代理的优势,下面介绍一种更实用的动态代理机制。

改进前:

改进后:

改进后的说明:代码段1、代码段2、代码段3和深色代码段分离开了,但代码段1、2、3又和一个特定的方法A耦合了!最理想的效果是:代码块1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用深色代码的方法。

  • 使用Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有太大的意义。通常都是为指定的目标对象生成动态代理

  • 这种动态代理在AOP中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理

简单的AOP与动态代理的例子:

package com.test.proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
 * CLassName: AOPTest
 * Package: com.test.proxy
 * Description:  简单的AOP与动态代理的例子
 * @Author: JOKER-wqc
 * @Version: v1.0
 */
 
 
    //使用了DynamicProxyTest中的Human 、 SuperMan
 
class HumanUtil{
    public void method1(){
        System.out.println("--------------通用方法一----------------");
    }
    public void method2(){
        System.out.println("--------------通用方法二----------------");
    }
}
 
class AOPProxyFactory{
    //调用此方法:返回一个代理类的对象
    public static Object getInstance(Object c){
        myAOPInvocationHandler myAOPInvocationHandler = new myAOPInvocationHandler();
        myAOPInvocationHandler.bind(c);
        return Proxy.newProxyInstance(c.getClass().getClassLoader(),c.getClass().getInterfaces(),myAOPInvocationHandler);
    }
 
}
 
class myAOPInvocationHandler implements InvocationHandler {
 
    private Object obj;//需要使用被代理类的对象进行赋值
 
    public void bind(Object obj){
        this.obj = obj;
    }
    //当我们通过代理类的对象,调用方法时,就会自动的调用如下方法invoke()
    //讲被代理类要执行的方法的功能声明在invoke()中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        HumanUtil humanUtil = new HumanUtil();
        humanUtil.method1();
 
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        //obj:被代理类对象
        Object result = method.invoke(obj, args);//如原方法有返回值则本方法也可返回
        humanUtil.method2();
        return result;
    }
}
 
public class AOPTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //生成代理类对象
        Human proxyHuman = (Human) AOPProxyFactory.getInstance(superMan);
        //通过代理类自动调用被代理类中的同名方法
 
        proxyHuman.set("钢铁");
 
        /*
        结果显示:
        --------------通用方法一----------------
        我喜欢吃钢铁
        --------------通用方法二----------------
         */
 
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值