基于 JDK 实现动态代理
JDK 动态代理的原理是利用反射机制,在运行时创建代理类,必要条件是代理对象基于接口实现。
创建一个接口及其实现类。
public interface IService {
void sayHello();
}
public class JdkServiceImpl implements IService {
@Override
public void sayHello() {
System.out.println("Hello JAVA Proxy");
}
}
创建代理处理类,必须实现 InvocationHandler
接口。
@AllArgsConstructor
public class ServiceInvocationHandler implements InvocationHandler {
private final Object target;
@Override
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("-------- begin ----------");
Object result = method.invoke(target, args);
System.out.println("-------- end ----------");
return result;
}
}
执行动态代理
public class JdkProxyTest {
public static void main(String[] args) {
IService service = new JdkServiceImpl();
ServiceInvocationHandler handler = new ServiceInvocationHandler(service);
IService proxy = (IService) Proxy.newProxyInstance(JdkProxyTest.class.getClassLoader(), new Class[]{IService.class}, handler);
proxy.sayHello();
System.out.println();
System.out.println(proxy.getClass().getSimpleName() +
" extend " + proxy.getClass().getSuperclass().getSimpleName() +
" implements " + Arrays.stream(proxy.getClass().getInterfaces())
.map(Class::getSimpleName)
.collect(Collectors.joining(",")));
}
}
输出结果如下,可以看出在 sayHello
方法前后,执行了代理处理类中的代码输出,说明通过 JDK
动态代理实现了代理增强。
-------- begin ----------
Hello JAVA Proxy
-------- end ----------
$Proxy0 extend Proxy implements IService
最后一行的输出显示了动态生成的代理类的继承关系,该类实现代理对象的接口,JDK
动态代理的继承机制决定了只能对接口进行代理。
基于 Cglib 实现动态代理
Cglib 动态代理的原理是利用字节码技术,在运行时创建一个继承代理类的 class,所以代理对象不需要实现接口,但要求被代理类及方法必须不是 final 的
创建一个需要被代理的类
public class CglibServiceImpl {
public void sayHello() {
System.out.println("Hello Cglib Proxy");
}
}
创建方法拦截器,必须实现 MethodInterceptor
接口,实现代理增强
public class ServiceInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
System.out.println("-------- begin ----------");
Object result = methodProxy.invokeSuper(obj, params);
System.out.println("-------- end ----------");
return result;
}
}
执行代理操作
public class CglibProxyTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibServiceImpl.class);
enhancer.setCallback(new ServiceInterceptor());
CglibServiceImpl proxy = (CglibServiceImpl) enhancer.create();
proxy.sayHello();
System.out.println();
System.out.println(proxy.getClass().getSimpleName() +
" extend " + proxy.getClass().getSuperclass().getSimpleName() +
" implements " + Arrays.stream(proxy.getClass().getInterfaces())
.map(Class::getSimpleName)
.collect(Collectors.joining(",")));
}
}
输出结果如下
-------- begin ----------
Hello Cglib Proxy
-------- end ----------
ServiceImpl$$EnhancerByCGLIB$$ef25c05 extend ServiceImpl implements Factory
基于 Spring 的 ProxyFactory 实现动态代理
Spring 也提供了自己动态代理实现,但其实做的还是整合的工作,底层依然是基于上文中的两种技术。
创建方法拦截器,需要实现 MethodInterceptor
接口(这个接口在 org.aopalliance.intercept
包中,与 cglib
中的不是同一个)。
public class AopInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("-------- begin ----------");
Object result = invocation.proceed();
System.out.println("-------- end ----------");
return result;
}
}
执行代理操作
public class SpringProxyTest {
public static void main(String[] args) {
executeJdkProxy();
// executeCglibProxy();
}
public static void executeJdkProxy() {
ProxyFactory factory = new ProxyFactory();
factory.setInterfaces(IService.class);
factory.setTarget(new JdkServiceImpl());
factory.addAdvice(new AopInteceptor());
IService proxy = (IService) factory.getProxy();
proxy.sayHello();
printClassName(proxy);
}
public static void executeCglibProxy() {
ProxyFactory factory1 = new ProxyFactory();
factory1.setTarget(new CglibServiceImpl());
factory1.addAdvice(new AopInteceptor());
CglibServiceImpl proxy1 = (CglibServiceImpl) factory1.getProxy();
proxy1.sayHello();
printClassName(proxy1);
}
public static void printClassName(Object proxy) {
System.out.println();
System.out.println(proxy.getClass().getSimpleName() +
" extend " + proxy.getClass().getSuperclass().getSimpleName() +
" implements " + Arrays.stream(proxy.getClass().getInterfaces())
.map(Class::getSimpleName)
.collect(Collectors.joining(",")));
}
}
执行 executeJdkProxy
方法输出
-------- begin ----------
Hello World
-------- end ----------
$Proxy18 extend Proxy implements IService,SpringProxy,Advised,DecoratingProxy
执行 executeCglibProxy
方法输出
-------- begin ----------
Hello Cglib Proxy
-------- end ----------
CglibServiceImpl$$EnhancerBySpringCGLIB$$57b39275 extend CglibServiceImpl implements SpringProxy,Advised,Factory
通过最后输出的类继承结构可以看出在 ProxyFactory
之下的实现原理,executeJdkProxy
与 executeCglibProxy
方法不同的一点是调用 factory.setInterfaces
设置了接口,如果不设置接口,那么底层还是使用 cglib
实现,虽然最终呈现出来的效果是一样的。所以具体使用哪种方案实现,并不处决了代理对象是不是接口,而是有没有向 ProxyFactory
设置接口(当然设置接口的前提首先得实现接口)。
ProxyFactory 的实现源码分析
根据方法 getProxy
进行源码跟踪
public class ProxyFactory extends ProxyCreatorSupport {
public Object getProxy() {
return createAopProxy().getProxy();
}
}
createAopProxy
方法在其父类中实现,调用 AopProxyFactory.createAopProxy
方法创建一个 AopProxy
对象,AopProxyFactory
默认使用 DefaultAopProxyFactory
。
public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
}
在 DefaultAopProxyFactory
的 createAopProxy
方法,可以看到根据不同的条件会选择创建不同的 AopProxy
。
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
}
AopProxy
的实现类分别代表不同的实现策略
以 JdkDynamicAopProxy
的实现为例,可以看到最终调用的还是 JDK
提供的 Proxy.newProxyInstance()
方法创建代理对象。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
}