定义: 为其他对象提供一种代理,以控制对这个对象的访问

代理对象在客户端和目标对象之间起到中介的作用

类型: 结构性

 

适用场景

1、保护目标对象

2、增强目标对象

 

优点

代理模式能将代理对象与真实被调用的目标对象分离

一定程度上降低了系统的耦合度,扩展性好

保护目标对象

增强目标对象(如加before和after)

 

缺点:

代理模式会造成系统设计中类数目增加

在客户端和目标对象增加一个代理对象,会造成请求速度变慢

增加系统的复杂度

 

代理-扩展

静态代理

动态代理

CGLib代理

 

Spring 代理选择-扩展

当Bean有实现接口时,Spring就会用JDK的动态代理

当Bean没有实现接口时,Spring使用CGlib

可以强制使用Cglib

      在spring配置中加入 <aop:aspectj-autoproxy proxy-target-class="true" /> 

 

静态代理实践(另外一个静态代理的例子Spring AOP原理

1、创建实体Order

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;
    }
}

  

2、创建Dao层

 IOrderDao接口

public interface IOrderDao {
    int insert(Order order);
}

  IOrderDao接口实现

public class OrderDaoImpl implements  IOrderDao {
    @Override
    public int insert(Order order) {
        System.out.println("Dao层添加Order成功");
        return 1;
    }
}

  

3、创建服务层

创建IOrderService 接口

public interface IOrderService {

    int saveOrder(Order order);

}

  创建IOrderService 接口实现

public class OrderServiceImpl   implements  IOrderService{

    private IOrderDao iOrderDao;

    @Override
    public int saveOrder(Order order) {
        //Spring会自己注入,这里就直接注入了
        iOrderDao = new OrderDaoImpl();
        System.out.println("Service层调用Dao层添加Order");
        return  iOrderDao.insert(order);
    }
}

  

4、模拟Spring中分库的使用介绍

创建DynamicDataSource  

public class DynamicDataSource  extends AbstractRoutingDataSource{


    /**
     * 返回值代表使用哪个Db
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDBType();
    }
}

  创建DataSourceContextHolder 

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 (String)  CONTEXT_HOLDER.get();
    }

    public static  void clearDBType(){
         CONTEXT_HOLDER.remove();
    }

}

  

5、创建代理类

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){
        System.out.println("静态代理 before code");

        int userId = order.getUserId();
        int dbRouter = userId % 2;
        System.out.println("静态代理分配到【db" + dbRouter + "】处理数据");

        // TODO: 2020/1/27 设置dataSource
        DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
    }

    private void afterMethod(){
        System.out.println("静态代理 after code");
    }

}

  

  

6、测试

public class Test {


    public static void main(String[] args) {
        Order order = new Order();
        order.setUserId(2);
        OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
        orderServiceStaticProxy.saveOrder(order);
    }
}

  

7、UML图如下

代理模式
    




Spring AOP原理
Spring AOP原理

 

 

8、输出结果如下

静态代理 before code
静态代理分配到【db0】处理数据
静态代理 after code
Service层调用Dao层添加Order
Dao层添加Order成功

  

 

动态代理实践(另外一个动态代理的例子Spring AOP原理

1、创建动态代理类

public class OrderServiceDynamicProxy  implements InvocationHandler{

    private Object target;

    public OrderServiceDynamicProxy(Object target){
        this.target = target;
    }

    public Object build(){
        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: 2020/1/27 设置dataSource
        DataSourceContextHolder.setDBType("db" + String.valueOf(dbRouter));
    }


    private void afterMethod(){
        System.out.println("动代理 after code");
    }
}

  

2、测试

public class Test {


    public static void main(String[] args) {
        Order order = new Order();
        order.setUserId(2);
        IOrderService orderServiceDynamicProxy = (IOrderService)new OrderServiceDynamicProxy(new OrderServiceImpl()).build();
        orderServiceDynamicProxy.saveOrder(order);
    }
}

  

3、输出

动态代理 before code
动态代理分配到【db0】处理数据
Service层调用Dao层添加Order
Dao层添加Order成功
动代理 after code

  

代理模式在源码中的应用

1、JDK中的java .lang.reflet.Proxy类

2、Spring中的ProxyFactoryBean

代理模式
    




Spring AOP原理
Spring AOP原理

 

 核心的方法为getObject()

代理模式
    




Spring AOP原理
Spring AOP原理

 

 

 还有JdkDynamicAopProxy和CglibAopProxy

3、Mybatis中

MapperProxyFactory

代理模式
    




Spring AOP原理
Spring AOP原理

 

相关文章: