动态代理
2019-08-17 本文已影响0人
更真实
接口中方法调用前、调用后添加业务处理,添加权限处理、日志处理
1. 实现InvocationHandler接口
public class ServiceProxy implements InvocationHandler{
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 1
System.out.println(proxy.getClass().getName());// com.sun.proxy.$Proxy0
System.out.println(method.getName()+"执行前");// target中方法调用前
Object result=method.invoke(target, args);
System.out.println(method.getName()+"执行后");// target中方法调用后
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);// 2
}
public ServiceProxy(Object target) {// 3
this.target=target;
}
}
2. 调用接口
public class Client {
public static void main(String[] args) {
UserService userService=new UserServiceImpl();
ServiceProxy serviceProxy=new ServiceProxy(userService);
UserService userServiceProxy=(UserService)serviceProxy.getProxy();
userServiceProxy.getID();
}
}
原理
代码2
Proxy.newProxyInstance
时JDK动态生成字节码并添加到虚拟机中
1. 动态生成的类
com.sun.proxy.$Proxy0(0为递增的一个数字)
动态生成的类$Proxy0
继承Proxy类并实现了UserService接口。
代码2,在Proxy.newProxyInstance时传入了this,所有的具体业务都委托给了this,当执行userServiceProxy中的方法时最后是通过调用serviceProxy的invoke方法执行具体业务。
代码3,在实例化ServiceProxy
时传入了userService
Proxy.newProxyInstance
生成的字节码没有把ServiceProxy
、UserServiceImpl
中的代码都拷贝到新生成的$Proxy0
的类中而是把具体的业务委托给UserService
实例、ServiceProxy
实例