动态代理
代理
Java有两种代理方式,一种是静态代理,另一种是动态代理。对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节。很多 API 就是通过这种形式来封装的
代理模式给某一个(目标)对象提供一个代理对象,并由代理对象持有目标对象的引用。所谓代理,就是一个对象代表另一个对象执行相应的动作程序。而代理对象可以在客户端和目标对象之间起到中介的作用。
静态代理
在程序运行之前确定代理角色,并且明确代理类和目标类的关系。
实例
目标类
class TargetObj {
public void execute (){
System.out.println("目标类方法执行...");
}
}
代理类
class ProxyObj {
private TargetObj targetObj ;
/**
* 持有目标对象
*/
public ProxyObj (TargetObj targetObj){
this.targetObj = targetObj ;
}
/**
* 目标对象方法调用
*/
public void invoke (){
before () ;
targetObj.execute();
after () ;
}
/**
* 前后置处理
*/
public void before (){
System.out.println("代理对象前置处理...");
}
public void after (){
System.out.println("代理对象后置处理...");
}
}
使用
public class Proxy01 {
public static void main(String[] args) {
TargetObj targetObj = new TargetObj() ;
ProxyObj proxyObj = new ProxyObj(targetObj) ;
proxyObj.invoke();
}
}
缺点
在实际的开发过程中,不可能为每个目标对象都定义一个代理类,同样也不能让一个代理对象去代理多个目标对象,这两种方式的维护成本都极高。
动态代理
基于Java反射机制,在JVM运行时动态创建和生成代理对象。
实例
目标类
class Target implements User {
@Override
public Integer update(String name) {
...
}
}
中间代理执行类
class UserHandler implements InvocationHandler {
private Object target ;
public UserHandler (Object target){
this.target = target ;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before()...");
Object result = method.invoke(target, args);
System.out.println("after()...");
return result;
}
}
使用
public static void main(String[] args) {
/*
* 生成$Proxy0的class文件
*/
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
/*
* 目标对象信息
*/
Target target = new Target();
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = Target.class.getInterfaces() ;
/*
* 创建代理对象
*/
InvocationHandler userHandler = new UserHandler(target);
/*
* 代理类对象名
* proxyClassName=com.java.proxy.$Proxy0
*/
String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();
System.out.println("proxyClassName="+proxyClassName);
/*
* 具体业务实现模拟
*/
User user1 = (User) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
User user2 = (User) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
user1.update("xxx") ;
user2.update("sss") ;
}
newProxyInstance()
三个核心参数:
- ClassLoader:基于JVM运行过程,所以需要获取目标类UserService的类加载器;
- Interfaces:目标类UserService实现的接口,从面向对象来考虑,接口与实现分离,代理类通过实现IUser接口,模拟目标类的需求;
- InvocationHandler:代理类提供的功能封装即UserHandler,可以在目标方法调用前后做增强处理;