定义:
为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介的作用
结构型
适用场景:
保护对象
增强目标对象
优点:
代理模式能将代理对象与真实被调用的目标对象分离
一定程度上降低了系统的耦合度,扩展性好
保护目标对象
增强目标对象
缺点:
代理模式会造成系统设计中类的数目增加
在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
增加系统的复杂度
扩张:
静态代理
动态代理
CGLib代理
Spring代理选择:
当Bean有实现接口时,Spring就会用JDK动态代理
当Bean有没有实现接口时,Spring就会用CGLib动态代理
可以强制使用CGLib
在spring配置中加入 <aop:aspectj-autoproxy proxy-target-class=“true”/>
参考资料:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html
代理速度对比:
CGLib与JDK动态代理对比:万次执行下,JDK7、JDK8的JDK动态代理比CGLib快20%左右。
相关设计模式:
代理模式和装饰者模式
代理模式和适配器模式
Coding
静态代理:
//DTO
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 IOrderDaoImpl 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 IOrderServiceImpl implements IOrderService{
private IOrderDao iOrderDao;
@Override
public int saveOrder(Order order) {
iOrderDao = new IOrderDaoImpl();
System.out.println("Service层调用Dao层添加Order");
return iOrderDao.insert(order);
}
}
//代理类
public class OrderServiceStaticProxy {
private IOrderService iOrderService;
public int saveOrder(Order order) {
beforeMethod();
iOrderService = new IOrderServiceImpl();
Integer userId = order.getUserId();
Integer dbRouter = userId % 2;
System.out.println("静态代理分配到【db"+dbRouter+"】数据处理");
DataSourceContextHolder.setDBType(String.valueOf("db"+dbRouter));
int i = iOrderService.saveOrder(order);
afterMethod();
return i;
}
private void beforeMethod() {
System.out.println("静态代理 before code");
}
private void afterMethod() {
System.out.println("静态代理 after code");
}
}
//多数据源选择器
public class DataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
public static void setDBType(String dbType) {
CONTEXT_HOLDER.set(dbType);
}
public static String getDBType() {
return CONTEXT_HOLDER.get();
}
public static void clearDBType() {
CONTEXT_HOLDER.remove();
}
}
//多数据源的实现类
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDBType();
}
// <!--多数据源配置 parent指向上面的配置数据库的连接池abstractDataSource 这里配置了两个数据源-->
// <bean id="dataSource1" parent="abstractDataSource">
// <property name="url" value="${jdbc_url}" />
// <property name="username" value="${jdbc_user}" />
// <property name="password" value="${jdbc_password}" />
// </bean>
// <bean id="dataSource2" parent="abstractDataSource">
// <property name="url" value="${jdbc_url_s}" />
// <property name="username" value="${jdbc_user_s}" />
// <property name="password" value="${jdbc_password_s}" />
// </bean>
//
// <!-- 在RoutingDataSource类中读取 当前的返回值 并匹配key值 选择你的数据库源-->
// <bean id="dataSource" class="com.alex.dao.RoutingDataSource">
// <property name="targetDataSources">
// <map key-type="java.lang.String">
// <entry key="dataSource1" value-ref="dataSource1"></entry>
// <entry key="dataSource2" value-ref="dataSource2"></entry>
// </map>
// </property>
// <property name="defaultTargetDataSource" ref="dataSource1"></property>
// </bean>
//
// <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
// <!-- 数据源 -->
// <property name="dataSource" ref="dataSource"></property>
// <!-- 别名 -->
// <property name="typeAliasesPackage" value="com.alex.entity"></property>
// <!-- sql映射文件路径 -->
// <property name="mapperLocations" value="classpath*:mapping/*Mapper.xml"></property>
// </bean>
}
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.setUserId(2);
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
orderServiceStaticProxy.saveOrder(order);
}
}
静态代理 before code
静态代理分配到【db0】数据处理
Service层调用Dao层添加Order
Dao层添加order成功
静态代理 after code
动态代理: