设计模式课程 设计模式精讲 16-4 代理模式Coding-动态代理

1    代码演练

1.1  动态代理

2    疑难解答

2.1  动态代理invoke怎么执行的?

2.2  感觉这块理解的不是很好,下边有时间再看看

1    代码演练
1.1  动态代理

重点:

重点关注动态代理类

测试类:

package com.geely.design.pattern.structural.proxy.dynamicproxy;

import com.geely.design.pattern.structural.proxy.IOrderService;
import com.geely.design.pattern.structural.proxy.Order;
import com.geely.design.pattern.structural.proxy.OrderServiceImpl;

public class Test {
    public static void main(String [] args){
        Order order = new Order();
        order.setUserID(1);
        /**
         * new OrderServiceDynamicProxy(order) 该方法已经生成了一个新的代理类
         * 它的bind方法返回了原目标类,强转之后变成了原目标类。
         */
        IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
        //注意,执行saveOrder方法,最终会执行invode方法。
        orderServiceDynamicProxy.saveOrder(order);
    }
}

动态代理类:

package com.geely.design.pattern.structural.proxy.dynamicproxy;

import com.geely.design.pattern.structural.proxy.Order;
import com.geely.design.pattern.structural.proxy.db.DataSourceContextHolder;

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

/**
 * 目的:抽奖信息和订单等不同的类都可以通过这一个动态代理进行复用,不用每一个都写一个静态代理。
 * 这就是静态代理和动态代理的区别
 * 动态代理是自动生成的,静态代理需要显式的来描述和coding
 */
public class OrderServiceDynamicProxy implements InvocationHandler {
    //目标对象
    public Object target;

    //通过构造方法传入目标对象
    public OrderServiceDynamicProxy(Object target) {
        this.target = target;
    }

    /**
     * 主方法, 调用前置方法,主要方法,以及后置方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //取得目标对象,argObject是目标类,也就是静态代理demo中的订单类
        Object argObject = args[0];
        beforeMethod(argObject);
        Object object = method.invoke(target,args);
        afterMethod();
        return object;
    }

    public Object bind(){
        //得到目标对象的class类
        Class cls = target.getClass();
        //这里边有三个参数,classLoader,复数的interface,它的类型是class,第三个是invoccationHandler 因为本类本身实现了InvocationHandler,所以把本类自己传过去即可。
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
    }

    /**
     * 前置方法,用来取模运算
     * @param obj
     */
    private void beforeMethod(Object obj){
        int userID = 0;
        System.out.println("动态代理 before code");
        if(obj instanceof Order){//如果该对象属于Order类
            Order order = (Order) obj;//强转成Order 类
            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 code");
    }

}

订单类:

package com.geely.design.pattern.structural.proxy;

/**
 * 建立订单实体类
 */
public class Order {
    private Object orderInfo;
    //之所以选择integer类型,是为了方便OrderServiceStaticProxy静态代理类进行分库
    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:

package com.geely.design.pattern.structural.proxy;

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

订单daoIMPL:

package com.geely.design.pattern.structural.proxy;

public class OrderDaoImpl implements IOrderDao{
    @Override
    public int insertOrder(Order order) {
        System.out.println("新增一条订单!");
        return 1;
    }
}

订单Service:

package com.geely.design.pattern.structural.proxy;

public interface IOrderService {
    int saveOrder(Order order);
}

订单ServiceIMPL:

package com.geely.design.pattern.structural.proxy;

public class OrderServiceImpl implements IOrderService {
    private IOrderDao orderDao;

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

打印日志:

Connected to the target VM, address: ‘127.0.0.1:12906‘, transport: ‘socket‘
动态代理 before code
动态代理分配到 【db1】数据库进行处理数据!
Disconnected from the target VM, address: ‘127.0.0.1:12906‘, transport: ‘socket‘
Service层调用dao层添加Order
新增一条订单!
动态代理 after code

Process finished with exit code 0
2    疑难解答
2.1  动态代理invoke怎么执行的?

1.Proxy.newProxyInstance(//参数省略了...)的部分源码

2.程序运行时产生一个类$proxyQ
3.Sproxy0类继承自Proxy类,实现了目标对象的父类接口(借鉴的百度提供的源码

4.Sproxy0类有多个Method成员变量,它的静态代码块给Method赋值为我们自己的接口的实现类的对应的Method对象
5.Sproxyo实现接口的方法调用了super.h.invoke(参数),这里的参数包括Method变量

这样就缕顺了,整体流程:
代理对象调接口中的方法---代理对象的真身是$proxy0
调用了对应的方法---此方法内部调用其父类的成员h调用h的invoke方法---就是调用传入了InvocationHandler的invoke方法,至于返回值,那就看我们的InvocationHandler的实现类怎么写了。

这部分参考:https://www.jianshu.com/p/774c65290218

原文地址:https://www.cnblogs.com/1446358788-qq/p/11563452.html

时间: 2024-11-08 21:47:20

设计模式课程 设计模式精讲 16-4 代理模式Coding-动态代理的相关文章

Java设计模式-代理模式之动态代理(附源码分析)

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

Java设计模式-代理模式之动态代理(附源代码分析)

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

设计模式(11)--代理模式之动态代理

保护代理 在调用方法前后,进行一些动作. 动态代理之所以叫动态代理是因为,是运行时才将它的类创建出来. 日志 . 连接. 事务. Java在java.lang.reflect包中有自己的代理支持,利用这个包你可以要运行时动态地创建一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类.因为实际的代理类是在运行时创建类,我们称这个Java技术为:动态代理. Java为你创建Proxy类,因为Proxy不是你直接实现的,你让代理执行的代理应该放在InvocationHandler中. In

谈谈Java的代理模式及动态代理

Java的动态代理在实践中有着广泛的使用场景,比如最场景的Spring AOP.Java注解的获取.日志.用户鉴权等.本篇文章带大家了解一下代理模式.静态代理以及基于JDK原生动态代理. 代理模式无论学习静态代理或动态代理,我们都要先了解一下代理模式. 先看百度百科的定义: 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 直接看定义可能有些难以理解,我们就以生活中具体的实例

设计模式_代理模式_动态代理

转自:https://www.ibm.com/developerworks/cn/java/j-lo-proxy-pattern/index.html 动态代理是指在运行时动态生成代理类.即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader.与静态处理类相比,动态类有诸多好处.首先,不需要为真实主题写一个形式上完全一样的封装类,假如主题接口中的方法很多,为每一个接口写一个代理方法也很麻烦.如果接口有变动,则真实主题和代理类都要修改,不利于系统维护:其次,使用一些动态代理的生成

动态代理模式——JDK动态代理

今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理逻辑方法. 在Java中,有很多的动态代理技术.如:JDK.CGLIB.Javassist.ASM,其中最常用的动态代理技术有两种:一种是JDK动态代理,这是JDK自带的功能:另一种就是CGLIB,这是第三方提供的一种技术. 这次主要讲的是JDK动态代理和CGLIB动态代理.在JDK动态代理中,我们

代理模式之动态代理

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //接口 interface MyInterface { public void action(); } // 被代理类 class MyObject implements MyInterface { @Override public void action() { System.

程序设计优化——(2)代理模式之动态代理

简介:动态代理是指在运行时,动态生成代理类.即代理类的字节码将在运行时生成并载入当前的ClassLoader.与静态代理类相比,有诸多好处.不需要为真实主题写一个形式上完全一样的封装类,若接口过多,则会代理接口也很多,接口稍微改动,代理接口也要进行变更:其次,使用动态代理可以在运行时指定代理类的执行逻辑,从而提升系统的灵活性. 动态代理有JDK自带的动态代理,CGLIB.Javassist或者ASM库.JDK的动态代理简单,内置在JDK中,因此不需要引入第三方jar包,但功能较弱.CGLIB和J

设计模式课程 设计模式精讲 13-1 享元模式coding

1 代码演练 1.1 代码演练1 1.2 代码演练2 1.3 代码演练3 1.4 代码演练4 1 代码演练 1.1 代码演练1 1.2 代码演练2 1.3 代码演练3 1.4 代码演练4 原文地址:https://www.cnblogs.com/1446358788-qq/p/11518773.html