Notes on "Java Design Patterns"-Chapter 16 Agent Mode

statement:

This blog is my notes after studying "Java Design Patterns". It is intended to facilitate review and review, and is not for commercial use.

This blog has indicated the source, if there is any infringement, please inform and delete it immediately.

1. Explanation of agent mode

  • Definition: Provide a proxy for other objects to control access to this object

  • The proxy object acts as an intermediary between the client and the target object

  • Type: Structural

  • Applicable scene

    • Protect the target audience
    • Enhance the target audience
  • advantage

    • The proxy mode can separate the proxy object from the actual called target object
    • To a certain extent, the coupling degree of the system is reduced, and the scalability is good
    • Protect the target audience
    • Enhance the target audience
  • Disadvantage

    • The proxy mode will increase the number of classes in the system design
    • Adding a proxy object to the client and the target object will slow down the request processing speed
    • Increase the complexity of the system
  • Expand

    • Static proxy: display the specified proxy in the code
    • Dynamic proxy: Dynamic proxy cannot proxy classes, but can proxy interfaces, so the proxy class implements at least one interface, and methods that are not declared in the interface cannot be proxied. The proxy class used by the dynamic proxy is actually created by the JVM when the program calls the proxy class object.
    • CGlib proxy: CGlib can proxy classes, and it is proxy for class implementations. If we proxy a class, CGlib will generate a subclass of the proxy class and override the methods in it. When using the CGLib proxy, because inheritance and rewriting are required, the proxy class is a class that cannot be finalized, and the method in the proxy class that is finalized cannot be proxied.
  • Spring proxy selection

    • When the Bean has an implementation interface, Spring will use the dynamic proxy of the JDK
    • When the Bean does not implement the interface, Spring uses CGlib
    • Can be configured in Spring to force the use of CGlib
  • Related design patterns

    • Agent mode and decorator mode

      The decorator mode is to add behavior to the object, while the proxy mode is to control access. The proxy mode pays more attention to enhancing the target object by setting up a proxy.

    • Proxy mode and adapter mode

      The adapter mode mainly changes the interface of the considered object, while the proxy mode cannot change the interface of the proxy class.

2. Static Proxy Coding

Let's introduce a business scenario based on user Id for sub-database

  1. Create order class

    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. Create Dao layer interface and implementation class

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

    public interface IOrderService {
          
          
        int saveOrder(Order order);
    }
    
    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);
        }
    }
    
  4. Create a static proxy class, enhance the saveOrder method in OrderService, and realize the sub-library function

    package princinple.structural.proxy.staticproxy;
    
    import princinple.structural.proxy.IOrderService;
    import princinple.structural.proxy.Order;
    import princinple.structural.proxy.OrderServiceImpl;
    
    public class OrderServiceStaticProxy {
          
          
        private IOrderService iOrderService;
    
        public int saveOrder(Order order) {
          
          
            beforeMethod(order);
            int result = iOrderService.saveOrder(order);
            afterMethod();
            return result;
        }
    
        private void beforeMethod(Order order) {
          
          
            System.out.println("静态代理 before code");
            iOrderService = new OrderServiceImpl();
            int userId = order.getUserId();
            // 实现分库的功能
            int dbRouter = userId % 2;
            System.out.println("静态代理分配到【db" + dbRouter + "】处理数据");
        }
    
        private void afterMethod() {
          
          
            System.out.println("静态代理 after code");
        }
    }
    
    
  5. Test class

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

    operation result:

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

    After changing the userId to 2, the running result:

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

The class diagram now looks like this:

Insert picture description here

3. Dynamic Proxy Coding

Still the above business scenario, we use dynamic proxy implementation.

  1. Create a dynamic proxy class

    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;
        }
    
        public 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 + "】处理数据");
        }
    
        public void afterMethod() {
          
          
            System.out.println("动态代理after code");
        }
    }
    
  2. Test class

    public class Test {
          
          
        public static void main(String[] args) {
          
          
            Order order = new Order();
            order.setUserId(1);
    
            IOrderService orderService = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
            orderService.saveOrder(order);
        }
    }
    

    operation result:

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

    After changing the userId to 2, the running result:

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

Guess you like

Origin blog.csdn.net/bm1998/article/details/113138506