代理模式2-JDK动态代理

动态代理

静态代理比较麻烦,每次出现一个被代理类就需要为他们编写静态代理类,而动态代理就可以适应各种复杂的情况。

媒婆(婚介所)JDK动态代理类

public class JDKMeipo implements InvocationHandler {

    /**
     * 需要被代理的类对象
     */
    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Class clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(this.target, args);
        after();
        return obj;
    }

    private void before(){
        System.out.println("媒婆来了");
    }

    private void after(){
        System.out.println("介绍完了");
    }
}

被代理接口以及实现类

public interface Person {

    void findLove();

}

public class Customer implements Person{

    @Override
    public void findLove() {
        System.out.println("我的需求如下:");
        System.out.println("1. 180cm");
        System.out.println("2. 本地土著");
    }
}

测试

    @Test
    public void test1() {
        Person person = (Person) new JDKMeipo().getInstance(new Customer());
        person.findLove();
    }

结果:

媒婆来了
我的需求如下:
1. 180cm
2. 本地土著
介绍完了

jdk动态代理是根据interface接口代理的,需要实现InvocationHandler接口。

数据源动态路由

动态代理:

public class OrderServiceDynamicProxy implements InvocationHandler {

    private Object target;

    public Object getInstance(Object target){
        this.target = target;
        Class clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before(args[0]);
        Object object = method.invoke(target,args);
        after();
        return object;
    }

    private void before(Object param){
        try {
            System.out.println("代理之前执行代码...参数取第一个,调用getCreateTime来获取年份");
            SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
            Long time = (Long) param.getClass().getMethod("getCreateTime").invoke(param);
            Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time)));
            System.out.println("动态代理分配到【DB_"+dbRouter+"】数据源处理数据");
            DynamicDataSourceEntry.set(dbRouter);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void after(){
        System.out.println("代理执行之后代码...");
    }

}

测试:

    @Test
    public void test() throws ParseException {
        Order order = new Order();
        SimpleDateFormat sdf = new SimpleDateFormat("yyy/MM/dd");
        Date date = sdf.parse("2020/02/03");
        order.setCreateTime(date.getTime());

        IOrderService instance = (IOrderService) new OrderServiceDynamicProxy().getInstance(new OrderService());
        instance.createOrder(order);

    }

结果:

代理之前执行代码...参数取第一个,调用getCreateTime来获取年份
动态代理分配到【DB_2020】数据源处理数据
orderService创建订单
创建新order
代理执行之后代码...

小结

可以很明显看出来,上面的动态代理代码并不是很灵活,因为硬性规定是通过实体的getCreateTime()来获取相关参数,其实可以通过注解等形式来做的,这里不做扩展。

你可能感兴趣的:(代理模式2-JDK动态代理)