java之jdk动态代理

来源:互联网 发布:免费顶级域名注册 ml 编辑:程序博客网 时间:2024/05/21 09:35

背景:
在面向对象编程的世界里,一切事物都封装成类,类里面包含了成员变量和方法,方法里就是一系列的功能处理。
不同的类所特有的功能是不一样的。在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 worldinsert1hello worldupdate1==========================hello worldinsert2hello worldupdate2

解释:

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


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

阅读全文
0 0
原创粉丝点击