代理模式
一、代理模式介绍
1、定义与类型
定义:为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介的作用
类型:结构型
2、适用场景
保护目标对象
增强目标对象
3、优点
代理模式能将代理对象与真实被调用的目标对象分离
一定程度上降低了系统的耦合度,扩展性好
保护目标对象
增强目标对象
4、缺点
代理模式会造成系统设计中类的数目增加
在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
增加系统的复杂度
5、扩展
静态代理
动态代理
CGLib代理
6、Spring代理选择-扩展
当Bean有实现接口时,Spring就会用JDK的动态代理
当Bean没有实现接口时,Spring使用CGlib
可以强制使用Cglib
在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
参考资料:htpsi//docs.spring.io/spring/docs/current/spring-framework-reference/core.html
7、代理-相关设计模式
代理模式和装饰者模式
实现上相似,但目的不同,装饰者模式是为对象加上行为,而代理模式是为了控制访问,代理模式更加注重通过增加代理人的方式来增强目标对象。
代理模式和适配器模式
适配器模式主要考虑改变目标对象的接口,而代理模式是不能改变代理类的接口的
二、代码示例
模拟场景:spring中,service调用dao前,需要先根据分库策略,切换数据源,即AOP面向切面
实体订单类:
public class Order {
private Object orderInfo;
private Integer userId;
public Object getOrderInfo() {
return orderInfo;
}
public void setOrderInfo(Object orderInfo) {
this.orderInfo = orderInfo;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
持久层dao接口:
public interface IOrderDao {
int insert(Order order);
}
持久层dao实现类:
public class OrderDaoImpl implements IOrderDao {
@Override
public int insert(Order order) {
System.out.println("Dao层添加Order成功");
return 1;
}
}
服务层service接口:
public interface IOrderService {
int saveOrder(Order order);
}
服务层service类:
public class OrderServiceImpl implements IOrderService {
private IOrderDao iOrderDao;
@Override
public int saveOrder(Order order) {
//模拟自动注入
iOrderDao = new OrderDaoImpl();
System.out.println("Service层调用Dao层添加Order");
return iOrderDao.insert(order);
}
}
1、静态代理
静态代理类:
public class OrderServiceStaticProxy {
private IOrderService iOrderService;
public int saveOrder(Order order){
beforeMethod(order);
// 模拟自动注入
iOrderService = new OrderServiceImpl();
int result = iOrderService.saveOrder(order);
afterMethod();
return result;
}
private void beforeMethod(Order order){
// 模拟分库代理操作
int userId = order.getUserId();
int dbRouter = userId % 2;
System.out.println("静态代理分配到【db"+dbRouter+"】处理数据");
//todo 设置dataSource;
DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
System.out.println("静态代理 before code");
}
private void afterMethod(){
System.out.println("静态代理 after code");
}
}
测试类:
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(2);
//直接调用代理类
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
orderServiceStaticProxy.saveOrder(order);
}
}
2、动态代理
动态代理类:
public class OrderServiceDynamicProxy implements InvocationHandler {
private Object target;
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
public Object bind(){
Class cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object argObject = args[0];
beforeMethod(argObject);
Object object = method.invoke(target,args);
afterMethod();
return object;
}
private void beforeMethod(Object obj){
int userId = 0;
System.out.println("动态代理 before code");
if(obj instanceof Order){
Order order = (Order)obj;
userId = order.getUserId();
}
int dbRouter = userId % 2;
System.out.println("动态代理分配到【db"+dbRouter+"】处理数据");
//todo 设置dataSource;
DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
}
private void afterMethod(){
System.out.println("动态代理 after code");
}
}
测试类:
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(1);
// 通过代理类取到service
IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
orderServiceDynamicProxy.saveOrder(order);
}
}