Java 反射之JDK动态代理

时间:2021-01-28 12:03:49

Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态的创建实例,也可以使用Proxy来创建动态代理实例。

Proxy提供了如下两个方法来创建动态代理类和动态代理类:

(1)、static Class<?>  getProxyClass(ClassLoader loader,Class<?> ...interfaces) : 创建一个动态代理类所对应的Class对象,该代理类将实现interfaces所指定的多个接口。第一个ClassLoader指定生成动态代理类的类加载器。

(2)、static Object newProxyInstance(ClassLoader loader,Class<?>  interfaces, InvocationHandler  h) :直接创建一个动态代理对象,该代理对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会被替换成执行          InvocationHandler对象的invoke方法。

实际上,即使采用第一种方式获取了一个动态代理类之后,当程序需要通过该代理类来创建对象时一样需要传入一个InvocationHandler对象。也就是说,系统生成的每个代理对象都有一个与之关联的InvocationHandler对象。

下面是AOP动态代理的实现:

在方法前后加入一写通用方法,比如项目中的日志记录。

Dog.java

package com.reflect.proxy;

public interface Dog {
public void info();
public void run();
}

GunDog.java

package com.reflect.proxy;

public class GunDog implements Dog {

	@Override
public void info() {
System.out.println("我是一只猎狗");
} @Override
public void run() {
System.out.println("我奔跑迅速");
} }

DogUtil.java

package com.reflect.proxy;

public class DogUtil {

	public void method1(){
System.out.println("=====模拟第1个通用方法======");
} public void method2(){
System.out.println("=====模拟第2个通用方法======");
} }

借助于Proxy和InvocationHandler就可以实现:当程序调用info()方法和run()方法时,系统就可以“自动” 将method1()和method2() 两个通用方法插入info()和run()犯法

package com.reflect.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { //需要被代理的对象
private Object target; public void setTarget(Object target){
this.target=target;
} //指定动态代理的所有方法时,都会替换成执行如下的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
DogUtil du=new DogUtil(); //执行DogUtil中的method1
du.method1();
//以target为主掉来执行method方法
Object result=method.invoke(target, args);
System.out.println(result);
//执行DogUtil中的Method2
du.method2();
return result;
} }

为指定的target生成代理类.

package com.reflect.proxy;

import java.lang.reflect.Proxy;

public class MyProxyFactory {

	//为指定target生成动态代理对象
public static Object getProxy(Object target){
MyInvocationHandler handler=new MyInvocationHandler();
//为MyInvotationHandler设置target对象
handler.setTarget(target);
//创建并返回一个动态代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
}

测试类

package com.reflect.proxy;

public class Test {

	public static void main(String[] args) {

		//创建一个原始的GunDog对象,作为target
Dog target=new GunDog();
//以指定的target创建动态代理
Dog dog=(Dog) MyProxyFactory.getProxy(target);
dog.info();
dog.run();
}
}

输出:

=====模拟第1个通用方法======
我是一只猎狗
=====模拟第2个通用方法====== =====模拟第1个通用方法======
我奔跑迅速
=====模拟第2个通用方法======