我们先说怎么实现JDK为我们提供的动态代理。(这篇文章目的是为Spring框架中的AOP思想提供技术支持)
0.用到反射包下的类,以及InvocationHandler接口。
Object | invoke(Object proxy, Method method, Object[] args) 在代理实例上处理方法调用并返回结果。 |
需要写自己的实现类。
问题1:为什么一定要实现这个接口?
1.自定义工厂类,以JDkProxyFactor为自己的工厂类。
代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JDkProxyFactory implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}
2.写自己的业务逻辑。
关于方法的参数的说明:
proxy--为谁产生代理
Method--为哪个方法产生代理
Args--这个方法需要哪些参数
代码结构图如下:
我就为Dog接口产生代理。
Dog接口有void bark()方法。
对象我不用他提供的Object proxy,我自己通过构造器注入一个。(没有注释请见谅)
private Object target;
public JDKProxyFactory(Object target) {
super();
this.target = target;
}
--------------------------------------------------------------------------------------------关键的一步到了------------------------------------
真理总是很简单,但人们却常常很难发现它。
我要做什么?为什么一定要这样做?为了AOP思想。
AOP思想是个神马玩意儿?是不改原来的代码但是又可以添加代码的神奇技术。
因此,我们需要在原来的类的基础上再克隆一个类,但是这个类写我们要添加的代码,然后运行的是这个类而不是原来的类。
我要产生这样一个字节码对象,更具体(在此文),我要产生Dog接口的对象,通过多态创建他子类哈士奇HashiQI的对象。
HaShiQi类:
package com.gzz.review;
public class HaShiQi implements Dog{
@Override
public void bark() {
System.out.println("主人给我骨头");
}
public void play() {
System.out.println("主人陪我玩");
}
}
怎么产生?
自己定义了一个方法用于得到我想要的类的对象。
提示需要一个classloader和一个接口和一个InvocationHandler。
通过读取当前线程的类的上下文获得classloader,让它去加载这个类
代码如下:
Thread.currentThread().getContextClassLoader()
还需要一个接口
通过查API,我知道了,interfaces
- 代理类要实现的接口列表
还记得我们通过构造器传过来的那个代理对象,那个对象在被创建的时候肯定是由多态创建了,其实那个对象是接口的实现类哈士奇对象。所以我们要得到那个接口,Dog。
同样的,在反射包下提供了获得接口的办法。
代码如下:
target.getClass().getInterfaces()
还需要一个参数,InvocationHadler。直接传this。因为这个JDkProxyFactory类实现了InvocationHadler接口。
我们就凑够了这个参数。
这样,就获得了那个类的对象。
然后搞测试。
创建一个测试类,就叫TestDog吧。
代码如下:
package com.gzz.review;
public class TestDog {
public static void main(String[] args) {
Dog dog = new HaShiQi();
JDkProxyFactory jDkProxyFactory = new JDkProxyFactory(dog);
Dog hashiqi = (Dog) jDkProxyFactory.getProxy();
hashiqi.bark();
}
}
这样我们就用JDK的方式实现了AOP思想。JDK动态代理技术的实现到此为止。
对了,还有问题一:我们可以写自己的实现AOP的类,但必须实现InvocationHandler这个接口,就像写Servlet就必须遵循sun公司帮我们制定好的xsd约束。这是一种规范,规范就必须遵循的。
值得说明,这种自己实现的技术有局限,局限是不能得到实现类的私有方法。本例中HaShiQi类的void play()方法就没有拿到。