JDK动态代理是Java中一种强大的机制,它允许在运行时创建代理对象,并拦截对这些对象方法的调用。Spring框架广泛使用JDK动态代理来实现AOP(Aspect-Oriented Programming)功能。下面将深入解析Spring源码,揭示JDK动态代理的工作原理。
JDK动态代理简介
JDK动态代理基于反射机制,它主要涉及两个核心接口:
1. `InvocationHandler`:定义了处理代理实例上的方法调用的逻辑。
2. `Proxy`:提供了静态方法来创建代理实例。
Spring 使用 JDK 动态代理的场景
Spring AOP在以下情况下会使用JDK动态代理:
- 目标对象实现了一个或多个接口。
- 没有强制使用CGLIB(即没有设置`proxyTargetClass=true`)。
JDK动态代理的核心类
`ProxyFactory`
`ProxyFactory`是Spring AOP框架中用于创建代理对象的重要类。它根据目标对象是否实现接口选择合适的代理策略。
```java public class ProxyFactory extends AdvisedSupport implements AopProxyFactory { // 省略其他代码... @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { return new CglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<?>[] interfaces = config.getProxiedInterfaces(); return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.isAssignableFrom(interfaces[0]))); } } ```
在上面的代码中,如果目标对象实现了接口且未强制使用CGLIB,`createAopProxy`方法会返回一个`JdkDynamicAopProxy`实例。
`JdkDynamicAopProxy`
`JdkDynamicAopProxy`类负责使用JDK动态代理创建代理对象。
```java public class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { private final AdvisedSupport advised; public JdkDynamicAopProxy(AdvisedSupport config) { Assert.notNull(config, "AdvisedSupport must not be null"); this.advised = config; } @Override public Object getProxy(@Nullable ClassLoader classLoader) { return Proxy.newProxyInstance(classLoader, this.advised.getProxiedInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, this.advised.getTargetSource().getTarget(), method, args, this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, this.advised.getTargetClass())); return invocation.proceed(); } } ```
1. 在`getProxy`方法中,通过`Proxy.newProxyInstance`创建代理实例,该实例会将所有方法调用委托给`invoke`方法。
2. `invoke`方法是代理实例的核心逻辑。它创建一个`MethodInvocation`对象并调用其`proceed`方法,以执行链式拦截器和目标方法。
`ReflectiveMethodInvocation`
`ReflectiveMethodInvocation`是Spring AOP中具体的方法调用实现。
```java public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable { protected final Object proxy; protected final Object target; protected final Method method; protected Object[] arguments; private final List<Object> interceptorsAndDynamicMethodMatchers; private int currentInterceptorIndex = -1; public ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] arguments, List<Object> interceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.method = method; this.arguments = arguments; this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; } @Override public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.method.invoke(this.target, this.arguments); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) { MethodInterceptor interceptor = (MethodInterceptor) interceptorOrInterceptionAdvice; return interceptor.invoke(this); } else { return proceed(); } } } ```
1. `proceed`方法是拦截器链执行的核心。
2. 如果所有拦截器都已执行,则直接调用目标方法。
3. 否则,获取下一个拦截器并调用其`invoke`方法。
示例代码
让我们通过一个简单的例子来展示Spring中JDK动态代理的实际应用。
示例接口和实现
```java public interface HelloService { void sayHello(); } public class HelloServiceImpl implements HelloService { @Override public void sayHello() { System.out.println("Hello, World!"); } } ```
自定义拦截器
```java public class CustomInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("Before method: " + invocation.getMethod().getName()); Object result = invocation.proceed(); System.out.println("After method: " + invocation.getMethod().getName()); return result; } } ```
创建代理并使用
```java public class Main { public static void main(String[] args) { HelloService target = new HelloServiceImpl(); ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTarget(target); proxyFactory.addAdvice(new CustomInterceptor()); HelloService proxy = (HelloService) proxyFactory.getProxy(); proxy.sayHello(); } } ``` #### 输出 ``` Before method: sayHello Hello, World! After method: sayHello ```
总结
通过深入解析Spring的源码,我们了解了JDK动态代理是如何在Spring AOP中工作的。`ProxyFactory`根据目标对象的情况选择合适的代理实现,而`JdkDynamicAopProxy`通过`Proxy.newProxyInstance`创建代理对象,并在`invoke`方法中管理拦截器的执行。最后,通过`ReflectiveMethodInvocation`类,Spring实现了对方法调用的拦截和增强。这种设计使得Spring AOP能够灵活地处理各种切面需求,提供了强大的AOP功能。