一.定义
为其他对象提供一种代理,以控制这个对象的访问
二.使用场景
- 1.保护目标对象
- 2.增强目标对象
三.优缺点
1.优点
- 将代理对象与目与真实的被调用的目标对象分离
- 一定程度上降低了系统的耦合度,扩展性好
- 保护目标对象
2.缺点
- 造成系统设计中类的数目增加
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
- 增加了系统的复杂度
四.角色
- 代理对象:类似于中介
- 目标对象:被代理的对象
- 客户端:调用端
五.分类
1.静态代理 : 直接指定代理类
静态代理的步骤:
- 定义代理行为接口
- 代理对象和目标对象都要实现代理行为接口
- 代理对象直接调用目标对象的代理行为方法
2.动态代理:通过反射等动态指定代理类
(1) JDK的Proxy
步骤:
- 定义代理行为接口
- 目标对象实现代理行为接口
- 定义代理行为处理器(要实现InvocationHandler接口,通过的反射的方式来调用目标对象的代理行为方法)
- 通过Proxy.newProxyInstance来生成代理对象,使用代理对象调用代理行为方法
要求:
- 要定义代理接口,才能调用接口实现类
(2)CGLIB:将目标对象指定代理对象的父类,来直接调用父类的代理行为接口
步骤
- 定义目标对象
- 定义代理拦截器,实现Callback接口
- 实例化Enhancer对象
- 设置enhancer对象的父类
- 设置enhancer的回调对象
- 创建代理对象
- 调用目标对象的代理行为方法
要求
- 目标类不能是final类,可以被继承
六、实例
通过一个租房的实例来说明,租房者即为目标对象,租房中介即为代理者(租房者通过租房中介租房,而不是直接跟房东租房)
1.静态代理实例
(1)租房要求实体
/**
* 租房要求
* @author shixinke
*/
public class Requirement {
/**
* 朝向
*/
private String towards;
/**
* 面积
*/
private Double area;
/**
* 价格
*/
private Double price;
/**
* 离公交站或地铁站的距离
*/
private Integer distance;
public Requirement(String towards, Double area, Double price, Integer distance) {
this.towards = towards;
this.area = area;
this.price = price;
this.distance = distance;
}
public String getTowards() {
return towards;
}
public Double getArea() {
return area;
}
public Double getPrice() {
return price;
}
public Integer getDistance() {
return distance;
}
}
(2)租房接口(代理行为定义)
/**
* 出租接口
* @author shixinke
*/
public interface Rentable {
/**
* 租房子
* @return boolean
*/
boolean rent(Requirement requirement);
}
(3)租房人(目标对象)实现租房的接口
/**
* 租房子的人
* @author shixinke
*/
public class Tenant implements Rentable {
/**
* 自己亲自找房源租房
* @param requirement
* @return
*/
public boolean rent(Requirement requirement) {
System.out.println("求租,要求:面积:"+requirement.getArea() + ";朝向:"+requirement.getTowards() +";距离公交或地铁站距离:"+requirement.getDistance() +";价格:"+requirement.getPrice());
System.out.println("房子合适,决定签订合同");
return true;
}
}
(4)代理对象实现代理行为接口
/**
* 租房中介
* @author shixinke
*/
public class RentProxy implements Rentable {
/**
* 目标用户
*/
private Rentable target;
public RentProxy(Rentable target) {
this.target = target;
}
/**
* 房产中介代理租房
* @param requirement
* @return
*/
public boolean rent(Requirement requirement) {
System.out.println("房产中介为您找到了匹配的结果:");
//直接调用代理目标对象的代理行为方法
target.rent(requirement);
System.out.println("向房产中介交纳手续费,以及对房产中介进行评价");
return true;
}
}
2.JDK动态代理的实例
(1)定义要求实体
与静态代理的定义相同,不再赘述
(2)定义代理行为接口
与静态代理的定义相同,不再赘述
(3)定义目标对象,实现代理行为接口
与静态代理的定义相同,不再赘述
(4)定义代理行为处理器,实现InvocationHandler接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 租房代理处理
* @author shixinke
*/
public class RentInvocationHandler implements InvocationHandler {
private Rentable target;
//将目标对象传入进来
public RentInvocationHandler(Rentable target) {
this.target = target;
}
/**
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("房产中介为您找到了匹配的结果:");
//通过反射调用目标对象的代理方法
Object result = method.invoke(target, args);
System.out.println("向房产中介交纳手续费,以及对房产中介进行评价");
return result;
}
}
(5)测试代码
import java.lang.reflect.Proxy;
/**
* 动态代理测试
* @author shixinke
*/
public class DynamicProxyTest {
public static void main(String[] args) {
Rentable target = new Tenant();
Requirement requirement = new Requirement(
"朝南",
60D,
3000D,
800
);
//生成代理对象(要进行强转)
Rentable proxy = (Rentable) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new RentInvocationHandler(target)
);
//调用代理对象的代理行为方法
proxy.rent(requirement);
}
}
3.CGLIB实现动态代理实例
maven依赖包:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
(1)定义要求实体
与静态代理的定义相同,不再赘述
(2)定义目标对象,实现代理行为接口
与静态代理的定义相同,不再赘述
(3)定义代理拦截器,实现Callback接口
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 租房拦截器
*/
public class RentInterceptor implements MethodInterceptor {
/**
* 拦截操作
* @param o
* @param method
* @param objects
* @param methodProxy
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("房产中介为您找到了匹配的结果:");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("向房产中介交纳手续费,以及对房产中介进行评价");
return result;
}
}
(4)测试代码
import net.sf.cglib.proxy.Enhancer;
/**
* 通过Cglib实现动态代理
* @author shixinke
*/
public class CglibProxyTest {
public static void main(String[] args) {
Requirement requirement = new Requirement(
"朝南",
60D,
3000D,
800
);
//实例化Enhancer对象
Enhancer enhancer = new Enhancer();
// 设置enhancer对象的父类
enhancer.setSuperclass(Tenant.class);
// 设置enhancer的回调对象
enhancer.setCallback(new RentInterceptor());
// 创建代理对象
Tenant proxy= (Tenant) enhancer.create();
proxy.rent(requirement);
}
}