在以往的实现过程中,使用静态代理类,重复代码多,写作麻烦,我们通过重写IncocationHandler把代理动向注入的方式来写动态代理,使之成为工具类,在以后的调用过程中,我们就可以直接调用工具类的方法,来动态生成代理对象。
案例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//独立的用于生成动态代理对象的工具类
//这个类自动生成代理。
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy() {
//生成的代理类有三个参数,第一个是通过反射获取相应的代理实例,第二个是通过反射获取代理实现的接口,第三个是处理方法就是它本身
//我们所讲的classLoader,就是负责把磁盘上的.class文件加载到JVM内存中,类加载器getClassLoader()
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//处理代理实例并返回结果。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现
//seeHouse();//当新增代理类的方法时,直接在此处加入即可,就把代理的对象方法传入新的代理
// log("add");//这样写死了,当删除一个方法时,也会添加add。所以这里我们用反射
log(method.getName());//通过反射获取方法的名字,赋值给log
Object result = method.invoke(target, args);
return result;
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
和之前的spring学习笔记5不同,我们把接口对象放开,在后面任何事件都可以来调用这个类,可以每个业务用一个类来实现不同的代理。
import com.kuang.demo02.UserService;
import com.kuang.demo02.UserServiceImpl;
//通过工具类,直接调用动态生成代理实现。
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService=new UserServiceImpl();
//代理角色,本身不存在
ProxyInvocationHandler pih=new ProxyInvocationHandler();
pih.setTarget(userService);//设置要代理的对象
//动态生成代理类
UserService proxy= (UserService) pih.getProxy();
proxy.add();
proxy.delete();
proxy.query();
proxy.update();
}
}
结果:
好处:
1.可以真实的角色的操作更加的纯粹,不用去关注一些公共的业务。
2.公共交给代理角色,实现了业务的分工
3.公共的业务发生扩展的时候,方便集中管理
4.一个动态代理类代理的是一个接口,一般就是对应的一类业务
5.一个动态代理类可以代理多个类,只要是实现了同一个接口。