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