动态代理从接触Java起就常被提及,但过去一直未深入探究,以往只是粗略了解便作罢。今日静下心来仔细钻研其使用过程,发现其实并不复杂。通过亲手实现一个示例,基本掌握了其核心原理与正确用法。只要耐心细致地学习,理解动态代理并非难事,关键在于真正动手实践并深入思考整个流程。
1、 动态代理的关键在于依据被代理对象a,生成对应的代理实例。
2、 该方法位于JDK的java.lang.reflect包中,是通过代理类Proxy来生成代理对象的方式。
3、 该方法包含三个参数。
4、 类加载器用于加载被代理对象的类,可通过反射调用 a.getClass().getClassLoader() 获取当前对象的类加载器实例。
5、 接口集合指被代理对象所实现的全部接口,而非方法列表。可通过反射机制调用 a.getClass().getInterfaces() 方法来获取这些接口信息。
6、 调用处理方法的句柄是关键,需自定义一个处理类H,实现InvocationHandler接口,该接口包含一个invoke方法,用于具体的方法调用处理逻辑。
7、 h 是该类的一个实例,获取代理对象后,调用其方法会自动触发 h 的 invoke 方法,再由 invoke 方法将调用转发至被代理对象 a 的对应方法。
8、 编写测试类,先模拟无代理场景的运行情况
9、 定义一个House类及其接口IHouse,House类包含名称属性,通过构造函数初始化,并提供buy方法用于实现购房功能。
10、 创建一个表示人的类,模拟小明,其中包含一个名为自行购房的方法,用于描述不依赖中介直接购买房屋的行为。
11、 创建测试类TestDynamicProxy,编写测试方法,声明一个名为小明的People对象和一个house房屋对象,随后让小明调用buyHouseByMyself方法,完成自行购房的操作流程。
12、 输出结果如下所示
13、 编写测试类,运用动态代理技术
14、 创建一个名为 MyInvocationHandler 的类,实现 InvocationHandler 接口,并重写其 invoke 方法。该类包含一个构造函数,接收一个参数 target,用于接收被代理的对象实例。通过此构造方式将目标对象传入,以便在调用方法时进行统一处理,从而实现动态代理功能,灵活控制目标方法的执行过程。
15、 该语句的作用是通过反射机制调用目标对象 target 的指定方法 method,传入相应的参数 args,并将该方法执行后的返回结果赋值给 object 变量,从而实现动态调用对象方法并获取其返回值。
16、 由于MyInvocationHandler类的构造方法接收Object类型参数,因此该调用处理器可适用于任意类型的对象实例,具有良好的通用性和灵活性,能够动态代理各类对象的操作调用过程。
17、 创建完MyInvocationHandler类后,便可获取代理对象。编写ProxyClass类并定义一个getDynamicProxy方法用于获取动态代理实例,该方法接收一个Object类型的参数,代表需要进行代理的目标对象,通过该对象实现动态代理的创建与调用处理机制。
18、 该类可用于获取任意对象的代理实例。
19、 创建代理对象时,需实例化一个MyInvocationHandler类的对象handle,并将其作为参数传入newProxyInstance方法。此后,所有通过proxy代理对象调用的方法,都会自动转发到handle的invoke方法中进行处理,实现对目标方法的拦截与增强操作。
20、 另外两个参数分别为被代理对象的类加载器及其所实现接口的集合。
21、 创建代理类后,进行测试,模拟通过代理完成购房流程。
22、 在People类中新增一个名为buyHouseByDynamicProxy的方法,该方法接收一个House类的实例作为参数。
23、 通过ProxyClass类获取房屋实例的代理对象houseProxy,并在该方法中调用其buy方法完成操作。
24、 在TestDynamicProxy类中编写名为testBuyHouseByProxy的测试方法,创建一个名为小红的People实例,通过调用buyHouseByDynamicProxy方法,利用动态代理机制执行购房操作,验证代理功能的正确性与实现效果。
25、 通过代理方式成功调用House类的buy方法,输出结果验证了调用过程。
26、 通过这个例子可以看出,无论提供何种对象,只需调用ProxyClass的getDynamicProxy方法,即可便捷地获得对应的代理实例,无需了解对象具体所属的类,体现出良好的通用性与灵活性,大大简化了代理对象的获取过程,提升了代码的复用性和扩展性。
27、 与静态代理不同,动态代理无需为每个被代理类单独创建代理类。静态代理中,每增加一个被代理类就需要编写对应的代理类,当被代理类数量庞大时,会导致类文件急剧增多,维护困难。
28、 例如,原本需要分别创建HouseProxy、FishProxy、CarProxy等代理类,通过引入动态代理机制,只需一个通用的ProxyClass即可实现相同功能,既避免了大量重复类的生成,又显著精简了代码结构,提升了系统的可维护性与扩展性。
29、 小明想买房,便通过代理类找到中介,由中介代为办理购房事宜,省时省力。
30、 代理在为小明购房时可执行特定操作,这些操作体现在MyInvocationHandler类的invoke方法中,即在method.invoke方法调用前后所进行的处理。
31、 通过动态代理机制,可实现Spring的AOP功能,例如为特定方法添加事务支持,或在方法执行前后记录日志信息,从而实现横切关注点的统一管理。
