一、JDK动态代理(只能代理接口,不能代理类)
主要用到这两个类 Proxy和InvocationHandler
Proxy,通过这个类的newProxyInstance方法可以创建代理类的实例对象。
InvocationHandler,动态代理类实现这个接口,可以对目标对象的方法进行处理
二、实现
接口
package com.sunshine.boot.proxy.jdk;
public interface IService {
void test1();
}
实现类
package com.sunshine.boot.proxy.jdk;
public class ServiceA implements IService{
@Override
public void test1() {
System.out.println("我是serviceA的test1方法");
}
}
动态代理类
package com.sunshine.boot.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk动态代理类
*/
public class JDKProxyTest implements InvocationHandler {
// 被代理的目标对象
private Object target;
public JDKProxyTest(Object target) {
this.target = target;
}
/**
*
* @param proxy 代理对象
* @param method 被代理对象的方法
* @param args 被代理对象的方法中的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行方法名称"+method.getName());
System.out.println("我是代理对象的before");
Object result = method.invoke(this.target, args);
System.out.println("我是代理对象的after");
return result;
}
public static <T> T createProxy(Object target, Class<T> targetInterface) {
if(!targetInterface.isInterface()) {
throw new RuntimeException("targetInterface必须是接口类型!");
}else if(!targetInterface.isAssignableFrom(target.getClass())) {
throw new RuntimeException("target必须是targetInterface接口的实现类!");
}else {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new JDKProxyTest(target));
}
}
}
三、测试
public static void main(String[] args) {
IService proxyA = JDKProxyTest.createProxy(new ServiceA(), IService.class);
proxyA.test1();
}
结果:
执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是代理对象的after
彩蛋
在idea中,我采用debug模式进行jdk动态代理测试,会出现下面结果
执行方法名称toString
我是代理对象的before
我是代理对象的after
执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是代理对象的after执行方法名称toString
我是代理对象的before
我是代理对象的after
查询网上资料发现,出现上述情况,是因为在debug模式下idea会调用被代理类的toString()方法。代理类会代理该类的所有方法,因此会重复输出。
补充:
JDK代理,当实现类中test1方法中调用test2方法,只是代理test1,不会在test1方法中代理test2
执行结果
执行方法名称test1
我是代理对象的before
我是serviceA的test1方法
我是serviceA的test2方法
我是代理对象的aftercglib代理,会代理所有方法,当test1方法中调用test2方法,这两个方法都会代理