1. 程式人生 > 其它 >java設計模式——動態代理示例

java設計模式——動態代理示例

技術標籤:java設計模式

動態代理示例實現動態分庫功能示例

1、程式碼結構如下圖:
在這裡插入圖片描述

2、建立訂單和使用者類

package com.rf.designPatterns.structural.proxy;

/**
 * @description: 訂單和使用者類
 * @author: xz
 */
public class Order {
    private Object orderId;//訂單id
    private Integer userId;//使用者id

    public Object getOrderId() {
        return orderId;
} public void setOrderId(Object orderId) { this.orderId = orderId; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } }

3、建立Service層

package com.rf.designPatterns.structural.proxy;

/**
 * @description: Service層
 * @author: xz
 */
public interface OrderService { int saveOrder(Order order); }

4、建立Dao層

package com.rf.designPatterns.structural.proxy;

/**
 * @description: Dao層
 * @author: xz
 */
public interface OrderDao {
    int insert(Order order);
}

5、建立Dao實現層

package com.rf.designPatterns.structural.proxy;

/**
 * @description: Dao實現層
 * @author: xz
 */
public class OrderDaoImpl implements OrderDao{ @Override public int insert(Order order) { System.out.println("Dao層新增訂單成功"); return 1; } }

6、建立Service實現層

package com.rf.designPatterns.structural.proxy;

/**
 * @description: Service實現層
 * @author: xz
 */
public class OrderServiceImpl implements OrderService{
    private OrderDao orderDao;
    @Override
    public int saveOrder(Order order) {
        //spring會自動注入,這裡我們自己直接new
        orderDao=new OrderDaoImpl();
        System.out.println("Service呼叫Dao層的inser方法新增訂單");
        orderDao.insert(order);
        return 1;
    }
}

7、建立資料來源上下文類

package com.rf.designPatterns.structural.proxy.db;

/**
 * @description: 資料來源上下文類
 * @author: xz
 */
public class DataSourceContextHolder {

    private static final ThreadLocal<String> CONTEXT_HOLDER=new ThreadLocal<String>();

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

}

8、建立動態的資料來源類

package com.rf.designPatterns.structural.proxy.db;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @description: 動態的資料來源類
 * @author: xz
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDBType();
    }
}

9、建立Service層的動態代理

package com.rf.designPatterns.structural.proxy.dynamicProxy;

import com.rf.designPatterns.structural.proxy.Order;
import com.rf.designPatterns.structural.proxy.db.DataSourceContextHolder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @description: Service層的動態代理
 * @author: xz
 */
public class OrderServiceDynamicProxy implements InvocationHandler {
    //宣告一個目標物件
    private Object target;

    //通過構造器新增目標物件
    public OrderServiceDynamicProxy(Object target) {
        this.target = target;
    }

    //繫結目標物件
    public Object bind(){
        Class cls=target.getClass();//獲取目標類的class物件
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
    }


    /**
     * @param proxy 動態生成的代理類
     * @param method 要被增強的方法物件
     * @param args method方法的引數
     * @return
     * @throws Throwable
     */
    @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){
        System.out.println("動態代理before程式碼, 在invoke方法之前執行");
        int userId=0;
        if(obj instanceof Order){
            Order order=(Order)obj;
            userId= order.getUserId();
        }
        int dbRouter=userId % 2;
        System.out.println("動態代理分配到 db【" +dbRouter+ "】 資料庫處理資料");
        DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
    }

    private void afterMethod(){
        System.out.println("動態代理after程式碼, 在invoke方法之後執行");
    }

}

10、建立測試類

package com.rf.designPatterns.structural.proxy.dynamicProxy;

import com.rf.designPatterns.structural.proxy.Order;
import com.rf.designPatterns.structural.proxy.OrderService;
import com.rf.designPatterns.structural.proxy.OrderServiceImpl;

public class Test {

    public static void main(String[] args) {

        Order order=new Order();
        //order.setUserId(1);
        order.setUserId(2);
        OrderService  orderServiceDynamicProxy = (OrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
        orderServiceDynamicProxy.saveOrder(order);

    }
}

11、測試結果如下圖:

在這裡插入圖片描述