1、采用JDK动态代理须知
(1)采用JDK动态代理实现AOP必须要使代理类和被代理类实现同一个接口。
(2)代理类实现接口的方式是通过反射在内存中形成,然后在通过类加载器加载到方法区的。所以和我们平时通过implement进行实现的编写方式不一样,但底层原理一样。
(3)我们最后调用方法时是调用代理类实现的方法,而代理类中的方法又调用了被代理类的方法。
2、场景模拟
(1)定义一个接口名称为TaergetInterface,里面有一个方法f(int x,int y),该方法用于计算两数之和并输出。
(2)编写一个类实现这个接口,并实现这个方法f(int x,int y)。
(3)在每次调用f(int x,int y)方法时,在该方法的输出语句前后随便BB几句。
3、代码编写
(1)定义一个接口名称为TaergetInterface,里面有一个方法f(int x,int y),该方法用于计算两数之和并输出。
/** * @author 齐天大圣 * @Version 1.0 */ public interface TaergetInterface { public void f(int x,int y); }
(2)编写一个类实现这个接口,并实现这个方法f(int x,int y)。
/** * @author 齐天大圣 * @Version 1.0 */ public class Target implements TaergetInterface{ @Override public void f(int x,int y) { System.out.println("x+y="+(x+y)); } }
(3)在每次调用f(int x,int y)方法时,在该方法的输出语句前后随便BB几句。
/** * @author 齐天大圣 * @Version 1.0 */ public class JDKProxy { public static void main(String[] args) { Target target = new Target(); ClassLoader classLoader = JDKProxy.class.getClassLoader(); TaergetInterface proxyInstance = (TaergetInterface)Proxy.newProxyInstance(classLoader, new Class[]{TaergetInterface.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我在调用方法的前面随便BB"); method.invoke(target, args); System.out.println("我在调用方法的后面随便BB"); return null; } }); proxyInstance.f(7,8); } }
输出结果
4、代码说明(参数意义)
TaergetInterface接口:就是一个接口
Target类:就是一个实现了TaergetInterface接口的类
上述就完成了两大部分
接下来就该说一下代理类了。
(1)Proxy.newProxyInstance(参数1,参数2,参数3)
该函数就是用来创建代理类的,该函数的反回值就是代理类。
(2)参数1
类加载器,就是将我们动态在内存中生成的代理类加载到方法区的。
(3)参数2
上面说过代理类需要实现接口,这个地方的参数就是接口。
(4)参数3
既然代理类已经实现了接口,当然要实现其中的方法,这个参数就是用来写参数的内容的。
参数为InvocationHandle形式传输,它是一个接口,我们可以采用匿名类的方式实现其中的方法。
可以看到它只有一个方法
public Object invoke(Object proxy, Method method, Object[] args)
当我们使用代理类调用接口中定义的方法时,其实就会调用到invoke方法。
(5)proxy:创建成功的代理类对象。
jdk底层自动传入该参数,不用我们管。
(6)method:正在执行的方法对象(就是代理类现在正在执行哪个方法)。
(7)args:代理类执行方法时传入的参数。
(8)invoke的方法体
(9)method.invoke(target, args)
我们平时都是通过 对象.方法(参数)进行调用方法的//通过对象找方法
这里是通过 方法.反射(被代理对象,参数)来调用的//通过方法找对象,因为代理类执行的方法就是被代理类要执行的方法
(10)整体流程