代理模式就是给对象提供一个代理,并由代理对象来控制原对象的引用,使得客户不能与真正的目标对象通信,代理对象是目标对象的代表, 其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉

静态代理

抽象角色:一般使用接口和抽象类来实现

public interface Rent {//抽象对象public void rent();}

真实角色:被代理的角色

public class Host implements Rent{@Overridepublic void rent() {System.out.println("房屋出租");}}

代理角色:代理真实角色

public class Proxy implements Rent{private Host host;public Proxy(Host host){this.host=host;}@Overridepublic void rent() {host.rent();}}

客户:使用代理角色进行操作

public class Client {public static void main(String[] args) {//房东要租房Host host = new Host();//中介帮房东Proxy proxy = new Proxy(host);//客户找中介proxy.rent();}}

优点:使真实角色更加存粹,公共业务由代理类来完成,满足开闭原则

缺点:多了代理类,工作量变大,对于框架场景不太适合

动态代理

基于接口的JDK代理

创建一个对象生成器,实现了InvocationHandler接口重写了invoke方法,被代理的目标对象要实现接口,通过接口来获取对象信息

public class ProxyInvocationHandler implements InvocationHandler {private Host host;public ProxyInvocationHandler(Host host){this.host = host;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object o = method.invoke(host, args);return o;}//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),host.getClass().getInterfaces(),this);}}

基于cglib代理

对于没有接口的类,想要实现动态代理,就需要cglib了,CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建 子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑

Cglib 子类代理实现方法:

1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所 以直接引入 spring-core-xxx.jar 即可.

2.引入功能包后,就可以在内存中动态构建子类

3.代理的类不能为 final,否则报错

4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额 外的业务方法.

publicclass CarFactoryImpl {publicvoid sell() {System.out.println("汽车厂卖汽车");}}
public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer = new Enhancer();public Object getProxy(Class clazz){enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}/* * 拦截所有目标类方法的调用* 参数:* obj目标实例对象* method 目标方法的反射对象* args 方法的参数* proxy 代理类的实例*/public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {//代理类调用父类的方法System.out.println("开始事务");Object obj1 = proxy.invokeSuper(obj, args);System.out.println("关闭事务");return obj1;}}
public class Test { public static void main(String[] args) {CGLibProxy proxy = new CGLibProxy();CarFactoryImpl carFactory = (CarFactoryImpl) proxy.getProxy(CarFactoryImpl.class);carFactory.sell();}}