jdk动态代理多种结构尝试,从经典实现到handler动态化

目录

一、jdk动态代理经典实现

1、被代理类实现的接口

2、被代理类(实现接口,重写方法)

3、代理类工厂(通过静态方法传入’被代理类对象(obj)‘获取‘代理对象(proxy)’)

4、创建InvocationHandler接口实现类

5、测试

6、结果

二、handler动态化

三、参数列表再简化

1、创建抽象类,对InvocationHandler 接口进行扩展(为的是解决obj的传入)

2、代理工厂静态方法改造

3、测试(通过NewHandler匿名内部类方式)


一、jdk动态代理经典实现

1、被代理类实现的接口

interface Human{
    //获取信仰
    String getBelif();
    //吃东西
    void eatFood(String foodName);
}

2、被代理类(实现接口,重写方法)

class Superman implements Human{

    //获取信仰
    @Override
    public String getBelif() {
        return "I belive that i can fly";
    }

    //吃东西
    @Override
    public void eatFood(String foodName) {
        //打印
        System.out.println("Superman is eating :" + foodName);
    }

}

3、代理类工厂(通过静态方法传入’被代理类对象(obj)‘获取‘代理对象(proxy)’)

class ProxyFactor{
    
    //静态方法获取代理对象
    public static Object getProxyInstance(Object obj){
        //创建InvocationHandler接口实现类对象
        Case01Handler case01Handler = new Case01Handler(obj);

        return Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),  //类加载器
                obj.getClass().getInterfaces(),   //接口列表
                case01Handler                       //handler
                );
    }

}

4、创建InvocationHandler接口实现类

class Case01Handler implements InvocationHandler{
    private Object obj;
    
    //通过构造器注入obj对象
    public Case01Handler(Object obj) {
        this.obj = obj;
    }
    
    //代理后将被调用的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("AOP(Case01Handler): 前");

        Object invoke = method.invoke(obj, args);

        System.out.println("AOP(Case01Handler): 后");

        return invoke;
    }
}

5、测试

public class DynamicProxyTest {

    public static void main(String[] args) {
        //创建被代理类对象
        Superman superman = new Superman();
        //获取代理对象
        Human supermanProx = (Human) ProxyFactor.getProxyInstance(superman);
        //方法1测试
        String belif = supermanProx.getBelif();
        System.out.println("belif = " + belif + "\n");
        //方法2测试
        supermanProx.eatFood("四川火锅");
    }

}

6、结果

二、handler动态化

        我们观察到,以上代理工厂的实现依赖于InvocationHandler类的实现类,

 那么,此代理工厂的代码结构即意味着:一个类型的代理工厂(ProxyFactor)只能对应一种aop处理方式的handler

这种结构在实际应用中当然没有争议,但是,如果我们想要实现代理工厂与handler实现的”一对多“,或者说实现handler的动态化,可以对代理工厂代码进行如下改动:

class ProxyFactor{
    
    //通过参数传入handler对象
    public static Object getProxyInstance(Object obj, InvocationHandler handler){

        return Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),
                handler
        );

    }

}

然后,我们可以有不同的方式传入hadler:

        1)经典地,根据被代理对象(obj)构造InvocationHandler 实现类对象,传入代理工厂获取代理对象,这里就不作演示了

        2)在测试类中通过匿名内部类,或者lambda表达式动态传入hadler到代理工厂,获取代理,这里演示lambda获取:

private static void test01() {
        //被代理对象
        Superman superman = new Superman();

        //获取代理
        Human supermanProx = (Human) ProxyFactor.getProxyInstance(
                superman,
                //lambda表达式
                (Object proxy, Method method, Object[] args) -> {
                    System.out.println("AOP(Case01Handler): 前");
                    Object invoke = method.invoke(superman, args);
                    System.out.println("AOP(Case01Handler): 后");
                    return invoke;
                }
        );

        //方法1测试
        String belif = supermanProx.getBelif();
        System.out.println("belif = " + belif + "\n");

        //方法2测试
        supermanProx.eatFood("四川火锅");

}

结果:

三、参数列表再简化

        如果大家觉得即传被代理对象,又传hadler实现很麻烦,这里还可以再简化api参数列表:

1、创建抽象类,对InvocationHandler 接口进行扩展(为的是解决obj的传入

//接口扩展
abstract class NewHandler implements InvocationHandler  {
     private Object obj;

    public NewHandler(Object obj) {
        this.obj = obj;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }
}

2、代理工厂静态方法改造

class ProxyFactor{

    //只需传入handler
    public static Object getProxyInstance(NewHandler handler){

        return Proxy.newProxyInstance(
                handler.getObj().getClass().getClassLoader(),
                handler.getObj().getClass().getInterfaces(),
                handler
        );

    }

}

3、测试(通过NewHandler匿名内部类方式)

private static void test06() {
        //被代理对象
        Superman superman = new Superman();
        //获取代理
        Human supermanProx = (Human) ProxyFactor.getProxyInstance(
                new NewHandler(superman) {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("AOP(Case01Handler): 前");
                        Object invoke = method.invoke(superman, args);
                        System.out.println("AOP(Case01Handler): 后");
                        return invoke;
                    }
                }
            );

        //方法1测试
        String belif = supermanProx.getBelif();
        System.out.println("belif = " + belif + "\n");
        //方法2测试
        supermanProx.eatFood("四川火锅");
    }

结果:

 最后,不管怎样改动,需要传入的被代理对象(obj)都没有消失,我们只是它的搬运工。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值