java之jdk动态代理

背景:
在面向对象编程的世界里,一切事物都封装成类,类里面包含了成员变量和方法,方法里就是一系列的功能处理。
不同的类所特有的功能是不一样的。在jdk里已经封装了很多的类,如果我们想对其中的某个类或者接口的功能进行拓展的话,只能是去继承或实现某个接口。

问题:
去拓展接口或现有类的功能时,需要去创建新的类,无形当中多了很多我们新建的类,如果有1000个人去实现某个接口拓展同样的功能,那就得新创建了1000个类,这样子不切实际。

解决:
如果对某个类或者接口拓展的功能是一样的 ,那么使用jdk动态代理,它可以不改变原有类或者接口的代码,去拓展额外的功能。然后每个人都可以使用同一个代理对象。说明了就是对现有类的封装,不直接去使用它,而是通过使用代理对象,那样不仅可以使用现有类的功能而且还能使用代理对象拓展的功能。

测试:

这里写图片描述

步骤一:
创建接口PersonDao、PersonDao2
创建实现类去实现接口PersonDao、PersonDao2,该类为目标类,需被代理

public interface PersonDao {
    public int insert();
    public int update();
}
public interface PersonDao2 {
    public int insert2();
    public int update2();
}
//目标类实现了2个接口
public class PersonDaoImpl implements PersonDao,PersonDao2{

    public int insert() {
        System.out.println("insert1");
        return 0;
    }

    public int update() {
        System.out.println("update1");
        return 0;



    }

    @Override
    public int insert2() {
        System.out.println("insert2");
        return 0;
    }

    @Override
    public int update2() {
        System.out.println("update2");
        return 0;
    }

}

步骤二:
获得代理对象

    public class App {
    public static void main(String[] args) {
        //获得系统类加载器
        ClassLoader loader = ClassLoader.getSystemClassLoader();

        //接口数组
        Class[] clazzs = {PersonDao.class,PersonDao2.class};

        //目标对象,需被传人处理器当中,在处理器调用目标对象的方法
        PersonDao dao = new PersonDaoImpl();

        //创建处理器对象
        InvocationHandler h = new MyInvocationHandler(dao);

        //创建动态代理对象
        Object  proxy =  Proxy.newProxyInstance(loader, clazzs, h);

        ((PersonDao)proxy).insert();
        ((PersonDao)proxy).update();
        System.out.println("==========================");
        ((PersonDao2)proxy).insert2();
        ((PersonDao2)proxy).update2();
    }
}

参数解释:
Object proxy = Proxy.newProxyInstance(loader, clazzs, h);

ClassLoader loader:类加载器
Class[] interfaces:接口数组
InvocationHandler:处理器,拓展额外的功能

步骤三:
自定义处理器

public class MyInvocationHandler implements InvocationHandler {

    //目标对象
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        //在调用目标类的方法之前打印hello world
        System.out.println("hello world");  

        //动态调用目标对象的方法,这里会动态调用,很厉害
        Object rs = method.invoke(target, args);
        return rs;
    }

解释:

该处理器的作用就是拓展目标类(persondaoimpl)的功能,步骤二当中获得代理对象时需要处理器的实例,而处理器是个接口,所以必须自定义创建处理器类的实现类。

步骤四:
测试结果

hello world
insert1
hello world
update1
==========================
hello world
insert2
hello world
update2

解释:

通过代理对象调用insert和update方法之前都打印了hello world


总结:
动态代理其实很简单,既然要动态代理就得有动态代理对象,既然得有对象那么就得去创建它,创建动态代理对象的时候需指定3个参数:类加载器、接口数组class、处理器。
关键的就是自定义创建处理器,它的功能就是拓展目标类的功能的,主要的方法就是invoke方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值