静态/动态代理模式
一、代理模式
AOP的底层机制就是动态代理!
代理模式:代理模式就是给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来说代理模式就是生活中常见的中介。
如下图所示:
-
用户只需要关心接口的功能,而不需要关心是谁提供了这个功能。
-
正在实现这个接口功能的是RealSubject,但是在开发过程中用户不直接与其接触而是通过代理来实现。
-
代理就是图中的Proxy,他也实现了接口功能并与客户直接接触
-
用户在调用Proxy时,Proxy内部调用了RealSubject。所以Proxy相当于中介,而且可以增强RealSubject的功能。

-
静态代理
-
动态代理
静态代理
静态代理角色分析:
-
抽象角色:一般使用接口或者抽象类来实现
-
真实角色:被代理的角色
-
代理角色:代理真实角色;代理真实角色后一般会做一些附属操作。
-
客户:使用代理角色来进行一些操作
代码实现
Rent.java 即抽象角色
//抽象角色:租房 public interface Rent { void rent(); }
Host.java:真实角色
//真实角色:房东,房东要出租房子 public class Host implements Rent { @Override public void rent() { System.out.println("房屋出租!"); } }
RentProxy.java:代理角色
public class RentProxy implements Rent { private Host host; public RentProxy(final Host host){ this.host = host; } @Override public void rent() { see(); host.rent(); fare(); } public void see(){ System.out.println("带客户看房!"); } public void fare(){ System.out.println("收中介费!"); } }
测试代码(客户)
public class MyTest { @Test public void test(){ //房东要租房 Host host = new Host(); //中介去帮助房东 RentProxy bhp = new RentProxy(host); //你去找中介 bhp.rent(); } }
分析:在这个过程中,我们并没有直接接触到房东,而是去找中介帮我们租房子,这就是所谓的代理模式。
静态代理的好处:
-
使我们真实地角色更加存粹,不需要关心无关的事情
-
其他的事情可以由代理来完成,实现了业务的分工
-
其他的事务发生扩展时容易
缺点:
-
类多了,多了代理类,工作量变大,开发效率变低
动态代理
-
动态代理的角色和静态代理的一样
-
动态代理的代理类是动态生成的,静态代理的代理类是我们提前写好的
-
动态代理分为两种:一类是基于接口动态代理,一类是基于类的动态代理
-
基于接口的动态代理:JDK动态代理
-
基于类的动态代理:cglib
-
现在用的较多的是javasist来生成的动态代理
-
JDK的动态代理需要了解两个类
核心:
-
InvocationHandler:调用处理程序
Object invoke(Object proxy, Method method, Object[]args); 参数: proxy - 调用该方法的代理实例 method - 代理实例的接口方法的实例 args - 方法的参数(理解的是这个意思)
-
Proxy
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 参数: loader:用哪个类加载器去加载代理对象 interfaces:动态代理需要实现的接口 h:动态代理方法在执行时,会调用h里面的invoke方法去执行
代码实现:
Rent.java 抽象角色
//抽象角色:租房 public interface Rent { void rent(); }
Host.java 真实角色
//真实角色:房东,房东要出租房子 public class Host implements Rent { @Override public void rent() { System.out.println("房屋出租!"); } }
ProxyInvocationHandler.java 代理角色
package com.aishimin.dao; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent){ this.rent = rent; } //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); } //在程序执行getProxy方法时,程序会自动跳转到这个方法执行 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { seeHouse(); //核心:本质上用反射来实现! Object result = method.invoke(rent,args); fare(); return result; } public void seeHouse(){ System.out.println("带房客看房!"); } public void fare(){ System.out.println("收中介费!"); } }
测试:
@Test public void test2(){ //真实角色 Host host = new Host(); //代理实例的调用处理程序 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //将真实地角色放置进去 pih.setRent(host); //动态生成对应的代理类 Rent proxy = (Rent) pih.getProxy(); proxy.rent(); }
深化理解:
实现一个通用的实现动态代理的类!
public class ProxyInvocationHandler implements InvocationHandler { private Object target; public void setRent(Object target){ this.target = target; } public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target,args); return result; } public void log(String methodName){ System.out.println("执行了"+methodName+"方法"); } }
动态代理的好处:
静态代理有的优点动态代理都有:
-
一个动态代理,一般代理的是某一类业务
-

浙公网安备 33010602011771号