举例
1 2 3 4
| public interface TestService { void sayHi(); void sayGood(); }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class TestServiceImpl implements TestService {
@Override public void sayHi() { System.out.println("HI"); }
@Override public void sayGood() { System.out.println("GOOD"); } }
|
main
1 2 3 4 5 6 7 8 9 10
| public class AppTest { @Test public void test01() { TestService testService=new TestServiceImpl(); testService.sayHi(); testService.sayGood(); }
}
|
需求
现在我需要在以上的两个方法之前分别要求输出现在的时间,以及在执行完之后输出“完成”。我们拥有以下几个方法
- 直接在sayHi,与saygood方法中添加
- 写一个工具类,调用工具类进行添加
以上的两个方法虽然有效,但是如果需要我们更改100个这样的方法,那样岂不是要更改100行
动态代理实现
动态代理可以在程序的执行过程创建代理对象,通过代理对象执行方法,增加额外方法
实现IncocationHandler,功能增加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.zss.handle;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Date;
public class MyIncation implements InvocationHandler { private Object object;
public MyIncation(Object object) { this.object = object; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object res=null; System.out.println(new Date()); res=method.invoke(object,args); System.out.println("完成"); return res; } }
|
创建代理
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class AppTest { @Test public void test01() { TestService testService=new TestServiceImpl(); InvocationHandler invocationHandler=new MyIncation(testService); TestService proxy=(TestService) Proxy.newProxyInstance(testService.getClass().getClassLoader(), testService.getClass().getInterfaces(),invocationHandler); proxy.sayGood(); proxy.sayHi(); } }
|
当然如果我们不想要sayhi方法执行一些代码,我们可以在实现IncocationHandler通过判断方法的名称,来选择执行哪一些代码
JDK动态代理是需要声明接口的,创建一个动态代理类必须得给这个”虚拟“的类一个接口。可以看到,这时候经动态代理类创造之后的每个bean已经不是原来那个对象了。
参考:
动态代理实际上是程序在运行中,根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程,通过反编译被生成的**$Proxy0.class**文件发现:
class类定义为:为何jdk动态代理必须有接口,不支持仅实现类的代理 - 简书 (jianshu.com)
public final class $Proxy0 extends Proxy implements Interface {
*public $Proxy0(InvocationHandler paramInvocationHandler) {*
*super(paramInvocationHandler);*
***}***
原理
原理不清楚,插眼!!