博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaEE - 15反射机制2

Posted on 2020-12-09 12:18  Kingdomer  阅读(104)  评论(0)    收藏  举报

JavaEE - 15动态代理2 

(7)反射的应用: 动态代理

(7.1)代理设计模式原理

  • 使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。
    • 代理对象决定是否以及何时将方法调用转到原始对象上。
  • 静态代理,特征是代理类和目标对象的类都是在编译期确定下来的,不利于程序扩展。
    • 每个代理类只能为一个接口服务,这样一来就比如产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
  • 动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
  • 动态代理使用场合
    • 调试
    • 远程方法调用
  • 动态代理相比于静态代理的优点
    • 抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。

(7.2)静态代理

//--接口
public interface ClothFactory {
    void productCloth();
}
// 代理类--------------------
public class ProxyClothFactory implements ClothFactory {
    // 用被代理类对象进行实例化
    private ClothFactory factory;
    public ProxyClothFactory(ClothFactory factory){
        this.factory = factory;
    }

    @Override
    public void productCloth() {
        System.out.println("代理工厂做准备工作");
        factory.productCloth();
        System.out.println("代理工厂做收尾工作");
    }
}
// 被代理类---------------------- public class NikeClothFactory implements ClothFactory{ @Override public void productCloth() { System.out.println("Nike工厂生产Nike运动服"); } }
// 测试---------------------- public class ProxyTest { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); ProxyClothFactory factory = new ProxyClothFactory(nikeClothFactory); factory.productCloth(); } }

(7.3)动态代理

  • 要想实现动态代理,需要解决的问题
    • 一是: 如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
    • 二是: 当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法。

接口及被代理类

public interface Human {
    String getBelief();
    void eat(String food);
}
//被代理类 -----------
public class SuperMan implements Human {
    @Override
    public String getBelief() {
        return "I can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("吃"+food);
    }
}

MyInvocationHandler

public class MyInvocationHandler implements InvocationHandler {
    private Object obj;
    public void bind(Object obj) {
        this.obj = obj;
    }

    // 当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法: invoke()
// 将被代理要执行的方法a 的功能声明在invoke()中。 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // method: 代理类对象调用的方法,此方法也是被代理类要调用的方法 // obj: 被代理类的对象
Object returnValue = method.invoke(obj, args); return returnValue; } }

ProxyFactory 代理工厂

public class ProxyFactory {
    // 调用此方法,返回一个代理类的对象,解决问题1
    public static Object getProxyInstance(Object obj){ //obj: 被代理类的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

测试 

public class ProxyTest {
    public static void main(String[] args){
        SuperMan superMan = new SuperMan();
        // proxyInstance: 代理类的对象
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        // 当通过代理类对象调用方法时,会自动调用被代理类中的同名的方法
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣烫");

        System.out.println("-------------------------");
        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        ClothFactory clothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
        clothFactory.productCloth();
    }
}

 

(7.4)动态代理与AOP(Aspect Orient Programming)

  • 代码段1、代码段2、代码段3都同时调用了特定方法A。
  • 理想效果:代码段1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用方法A。
  • AOP代理方法:   
    • 动态代理增加的通用方法1
    • 回调目标对象的方法
    • 动态代理增加的通用方法2 

通用方法类HumanUtil

public class HumanUtil {
    public void method1(){
        System.out.println("========通用方法1==========");
    }
    public void method2(){
        System.out.println("========通用方法2==========");
    }
}

 

MyInvocationHandler方法改进 

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // method: 代理类对象调用的方法,此方法也是被代理类要调用的方法
        // obj: 被代理类的对象
        HumanUtil humanUtil = new HumanUtil();
        humanUtil.method1();
        Object returnValue = method.invoke(obj, args);
        humanUtil.method2();
        return returnValue;
    }

 

执行结果:

========通用方法1==========
========通用方法2==========
I can fly
========通用方法1==========
吃四川麻辣烫
========通用方法2==========