文章目录
1. 什么是动态代理?
动态代理也是一种代理模式,利用了JDK API,
动态地在内存中构建代理对象
,从而实现对目标对象的代理功能,所以动态代理一般也叫JDK代理或者接口代理。Spring AOP的底层原理就是动态代理。
动态代理下,不需要开发人员手动编写目标对象的代理类,而是在运行的过程中,动态生成目标对象对应的代理类(Proxy.newProxyInstance()
),并且通过InvocationHandler接口
实现类对目标对象进行功能增强。
动态代理中目标对象是一定要实现接口的,否则无法使用动态代理
。
2. 动态代理与静态代理的区别
在上一节代理模式中讲到的静态代理模式中的静态代理对象是在编译期就已经实现了,编译完成后代理类是一个实际的class文件,而动态代理是在运行时动态生成的,即编译时没有生成实际的class文件,而是在运行时动态生成class文件,然后由类加载器加载到JVM中。
3. 动态代理的使用
在上一节代理模式中讲到静态代理的缺点违背了开闭原则,因为代理对象和目标对象都要实现一样的接口,所以新增或者修改接口,都需要在代理对象中新增和修改相应的接口实现方法,这大大降低了程序的扩展性和可维护性。而在动态代理中,程序员不用再定义代理对象,
每个代理对象都是动态生成的
,具体实现什么接口,根据代理的目标对象来确定,并且加入了对应的事件处理器(InvocationHandler)
,来拦截动态生成的代理对象中的每一个方法,然后进行增强功能。
还是以上一节中讲到的例子来分析,小张发现客户越来越多,需求也越来越多,再像以前那样,什么都自己干,会累死的,所以小张就去注册了一个中介公司,小明要租房子,小张就给安排一个代理中介1号提供相应的租房服务,小刘要买房子,小张就给安排一个代理中介2号提供相应的买房服务。不管是租房子还是卖房子,小张的中介公司都提供了标准化的服务流程,就是先装修房子,提高价格(前置处理),然后调用房主的租房子或者卖房子接口,最后成功了会通知房主(后置处理)。
从上面的例子可以看出,小张的中介公司要提供两个功能
- 动态创建目标对象(房东)对应的代理对象(中介)。(
Proxy.newProxyInstance()
) - 对于目标对象实现的接口方法,提供标准化的服务流程。(
InvocationHandler接口
)
下面就是动态代理下小张的中介公司的代码实现
public class ProxyCompany implements InvocationHandler {
//要代理的目标对象
private Object homeowner;
public Object getHomowner(){
return homeowner;
}
public void setHomeowner(Object homeowner) {
this.homeowner = homeowner;
}
//获取动态代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(homeowner.getClass().getClassLoader(),homeowner.getClass().getInterfaces(),this);
}
//拦截代理对象所有方法,提供标准化服务流程(功能增强)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强:装修房子,提高价格");
Object ret = method.invoke(homeowner,args);
System.out.println("后置增强:通知房主");
return ret;
}
}
客户端调用
public class Client {
public static void main(String[