大家都知道Spring中AOP是通过Java动态代理实现的,今天就来简单学习下demo。
Java动态代理主要有两个核心类,InvocationHandler和Proxy。
/**
* {@code InvocationHandler} is the interface implemented by
* the <i>invocation handler</i> of a proxy instance.
*
* <p>Each proxy instance has an associated invocation handler.
* When a method is invoked on a proxy instance, the method
* invocation is encoded and dispatched to the {@code invoke}
* method of its invocation handler.
*
* @author Peter Jones
* @see Proxy
* @since 1.3
*/
public interface InvocationHandler
所有的Handler类要实现InvocationHandler接口,并关联到Proxy实例上,最后会分发到InvocationHandler的invoke方法上。
/**
* {@code Proxy} provides static methods for creating dynamic proxy
* classes and instances, and it is also the superclass of all
* dynamic proxy classes created by those methods.
*
* <p>To create a proxy for some interface {@code Foo}:
* <pre>
* InvocationHandler handler = new MyInvocationHandler(...);
* Class proxyClass = Proxy.getProxyClass(
* Foo.class.getClassLoader(), new Class[] { Foo.class });
* Foo f = (Foo) proxyClass.
* getConstructor(new Class[] { InvocationHandler.class }).
* newInstance(new Object[] { handler });
* </pre>
* or more simply:
* <pre>
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
* new Class[] { Foo.class },
* handler);
* </pre>
*
****************************
*/
public class Proxy implements java.io.Serializable
通过该类的静态方法创建要动态代理的类。
下面看下demo
1. 先创建一个接口
public interface TargetInterface {
int targetMethod(int num);
}
2. 实例化该接口
public class TargetClass implements TargetInterface {
@Override
public int targetMethod(int number) {
System.out.println("调用目标类的方法targetMethod...");
return number;
}
}
3. 创建代理处理类,InvocationHandler子类
public class ProxyHandler implements InvocationHandler {
Object concreteClass;
public ProxyHandler(Object concreteClass) {
this.concreteClass = concreteClass;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("proxy:"+proxy.getClass().getName());
System.out.println("method:"+method.getName());
System.out.println("args:"+args[0].getClass().getName());
System.out.println("Before invoke method...");
Object object = method.invoke(concreteClass, args);
System.out.println("After invoke method...");
return object;
}
}
proxy: 指代我们所代理的那个真实对象 method: 指代的是我们所要调用真实对象的某个方法的Method对象 args: 指代的是调用真实对象某个方法时接受的参数
public class Example {
public static void main(String[] args) {
TargetClass cc = new TargetClass();
InvocationHandler ih = new ProxyHandler(cc);
TargetInterface tf = (TargetInterface) Proxy.newProxyInstance(cc.getClass().getClassLoader(), cc.getClass().getInterfaces(), ih);
int i = tf.targetMethod(5);
}
}
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
注意:通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
动态代理有个缺陷,就是创建时需要参数interfaces,即被代理的类,需要实现该接口。