现在有一个需求:在执行DemoImpl类的方法前后打印日志。你如何在不修改已有代码的前提下,完成这个需求?
当然静态代理、JDK动态代理、cglib动态代理都能实现,这里我们只用JDK动态代理实现
编写JDK动态代理基本步骤如下:
- 编写需要被代理的接口和类
- 编写代理类使用JDK自带Proxy类的newProxyInstance()方法获取代理类
- 使用代理类执行目标类(被代理类)的方法
DemoInterface接口:
public interface DemoInterface {
void hello(String msg);
String goodBye(String msg);
}
DemoImpl类:
public class DemoImpl implements DemoInterface{
@Override
public void hello(String msg) {
System.out.println("msg = " + msg);
}
@Override
public String goodBye(String msg) {
System.out.println("msg = " + msg);
return "这是goodbye方法的return";
}
}
当然静态代理、JDK动态代理、cglib动态代理都能实现,这里我们只用JDK动态代理实现
我们在DemoImpl类相同包下创建ProxyTest类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
DemoImpl demo = new DemoImpl();//实例化被代理对象(目标对象)
DemoInterface proxy = (DemoInterface)getProxy(demo);//获取代理对象。因其返回问Object对象需要强制转型
proxy.hello("hello world!");//代理对象执行目标对象里面的需要被代理的方法
String s = proxy.goodBye("goodbye world!");//另一个有返回值的方法
System.out.println(s);//输出返回值
}
//获取代理对象
private static Object getProxy(DemoImpl target){//接收目标对象并返回代理对象
/*
使用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法动态创建代理类对象。
newProxyInstance方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行
*/
Object proxyInstance = Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用方法前...");
Object returnValue = method.invoke(target, args);//通过反射执行方法
System.out.println("调用方法后...");
return returnValue;
}
}
);
return proxyInstance;
}
}
运行结果如下: