代理模式为某一个对象(委托类)提供一个代理(代理类),用来控制这个对象的访问。委托类和代理类有一个共同的父类或父接口。代理类会对请求做预处理、过滤、将请求的分配给指定对象。
代理模式的两个设计原则
- 代理类于委托类具有相似的行为
- 代理类增强委托类的行为
代理的三要素
- 有共同的行为 — 接口
- 目标角色 — 委托类,实现接口
- 代理角色 — 代理类,增加委托类的行为
静态代理
静态代理的特点
- 目标角色固定
- 在应用程序执行之前就得到了目标角色
- 代理对象会增强目标对象的行为
- 有可能存在多个代理,引起 “类爆炸”(缺点)
代码实现
共同的父接口1 2 3 4 5 6
| package org.example.house;
public interface IRentHouse { void toRentHouse(); }
|
委托类1 2 3 4 5 6 7 8
| package org.example.house;
public class RentHouseImpl implements IRentHouse{ @Override public void toRentHouse() { System.out.println("租房..."); } }
|
代理类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package org.example.house;
public class RentProxy implements IRentHouse{ private IRentHouse rentHouse;
public RentProxy(IRentHouse rentHouse) { this.rentHouse = rentHouse; }
@Override public void toRentHouse() { System.out.println("看房子..."); System.out.println("签署合同...");
this.rentHouse.toRentHouse();
System.out.println("售后服务..."); } }
|
测试,执行代理方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package org.example;
import org.example.house.IRentHouse; import org.example.house.RentHouseImpl; import org.example.house.RentProxy;
public class App { public static void main( String[] args ) { IRentHouse rentHouse = new RentHouseImpl();
RentProxy rentProxy = new RentProxy(rentHouse);
rentProxy.toRentHouse(); } }
|
动态代理
相比于静态代理,动态代理在创建代理对象上更加灵活,动态代理类的字节码在程序运行时,由Java反射机制动态生成。
动态代理的特点
- 目标对象(实现类)不固定
- 在应用程序执行时动态创建目标对象
- 代理对象会增强目标对象的行为
JDK 动态代理
JDK 动态代理的目标对象必须有接口实现,没有接口实现的类不能使用JDK动态代理。
JDK动态代理核心是使用 Proxy 代理类的 newProxyInstance 方法生成代理。
1
| public static Object newProxyInstance(ClassLoader loader, Class<T>[] interfaces, InvocationHandler h)
|
- 返回值:代理对象。
- loader:类加载器,定义了由哪些ClassLoader对象来对生成的代理对象进行加载
- interfaces: 一组目标对象和代理对象需要实现的接口
- h:回调接口,代理执行后调用的回调接口,构造器需要传递一个目标对象(委托对象),Invoke方法实现代理方法。
Jdk动态代理的实现过程
目标接口
- 创建目标类(委托类)的接口
租房接口1 2 3 4 5 6
| package org.example.house;
public interface IRentHouse { void toRentHouse(); }
|
目标类(委托类)
- 创建目标类(委托类),实现接口
IRentHouse
1 2 3 4 5 6 7 8
| package org.example.house;
public class RentHouseImpl implements IRentHouse{ @Override public void toRentHouse() { System.out.println("租房..."); } }
|
代理工厂
- 创建代理工厂,用来创建代理对象,相比静态代理,这里不再需要创建指定目标类(委托类)的代理类了。
方法一 创建 InvocationHandler 实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package org.example.dynamic;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class JdkProxyFactory{ private Object target;
public JdkProxyFactory(Object target) { this.target = target; }
public Object getProxy(){
ClassLoader classLoader = this.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("看房子..."); System.out.println("签署合同...");
Object result = method.invoke(target, args);
System.out.println("售后服务...");
return result; } };
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); return proxy; } }
|
方法二 代理工厂实现 InvocationHandler 接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| package org.example.dynamic;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class JdkProxyFactoryHandler implements InvocationHandler { private Object target;
public JdkProxyFactoryHandler(Object target) { this.target = target; }
public Object getProxy(){
ClassLoader classLoader = this.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler = this;
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); return proxy; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("看房子..."); System.out.println("签署合同...");
Object result = method.invoke(target, args);
System.out.println("售后服务...");
return result; } }
|
创建代理
- 使用代理工厂创建代理,执行代理任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.example;
import org.example.dynamic.JdkProxyFactory; import org.example.house.IRentHouse; import org.example.house.RentHouseImpl;
public class Starter {
public static void main(String[] args) { IRentHouse rentHouse = new RentHouseImpl();
JdkProxyFactory jdkProxyFactory = new JdkProxyFactory(rentHouse);
IRentHouse proxy = (IRentHouse) jdkProxyFactory.getProxy();
proxy.toRentHouse(); } }
|
执行结果如图
CGLIB 动态代理
cblib是针对类来实现代理的,可以在没有目标接口的情况下动态生成代理。它的原理是对指定的目标类生成一个子类,并覆盖其中的方法来实现行为增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。
引入依赖包 cglib
1 2 3 4 5
| <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
|
代理工厂
方法一 创建 MethodInterceptor 实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package org.example.dynamic;
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyFactory { private Object target;
public CglibProxyFactory(Object target) { this.target = target; }
public Object getProxy(){ Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
MethodInterceptor methodInterceptor = new MethodInterceptor() {
@Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("看房子..."); System.out.println("签署合同...");
Object result = method.invoke(target, objects);
System.out.println("售后服务...");
return result; } }; enhancer.setCallback(methodInterceptor);
return enhancer.create(); } }
|
方法二 实现 MethodInterceptor 接口的Cglib代理工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package org.example.dynamic;
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyFactoryHandler implements MethodInterceptor { private Object target;
public CglibProxyFactoryHandler(Object target) { this.target = target; }
public Object getProxy(){ Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
MethodInterceptor methodInterceptor = this;
enhancer.setCallback(methodInterceptor);
return enhancer.create(); }
@Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("看房子..."); System.out.println("签署合同...");
Object result = method.invoke(target, objects);
System.out.println("售后服务...");
return result; } }
|
创建代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.example;
import org.example.dynamic.CglibProxyFactory; import org.example.dynamic.JdkProxyFactory; import org.example.house.IRentHouse; import org.example.house.RentHouseImpl;
public class CglibStarter { public static void main(String[] args) { RentHouseImpl rentHouse = new RentHouseImpl();
CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(rentHouse);
RentHouseImpl proxy = (RentHouseImpl) cglibProxyFactory.getProxy();
proxy.toRentHouse(); } }
|