目录
第一类:【JDK代理】
JDK代理使用Demo
首先我们先来实现一个不依赖Spring框架的,单纯基于JDK的AOP代理:
目标类与其接口:
public interface TestAop {
void process();
}
@Component
public class TestAopImpl implements TestAop {
@Override
public void process() {
System.out.println("testAop.process()");
}
}
自定义的InvocationHandler:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("_____before");
Object result = method.invoke(target, args);
System.out.println("_____after");
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(),
this);
}
}
测试类:
public static void main(final String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
TestAop testAop = ac.getBean(TestAop.class);
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(testAop);
TestAop proxy = (TestAop) myInvocationHandler.getProxy();
proxy.process();
}
输出结果:
_____before
testAop.process()
_____after
JDK中AOP的实现是基于java.lang.reflect包中Proxy和InvocationHandler两个接口来实现的。
对于InvocationHandler的创建,需要我们重写三个方法:
- 构造函数:将目标代理对象传入;
- invoke:实现AOP中具体的逻辑;
- getProxy:获取产生的代理类;
而在Spring框架中,JDK方式的代理也是实现了上述过程,下面详细分析。
Spring框架中JDK代理源码分析
书接上文,在得到Advisors之后,通过proxyFactory.getProxy获取代理
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
假定createAopProxy中决定的实现类为JdkDynamicAopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
注意,这个类实现了接口InvocationHandler。
那么其中一定会有invoke方法的实现,就是AOP具体的逻辑:
1.1 invoke:实现AOP中具体的逻辑(是method维度)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
在次方法中:
- 获取当前方法的拦截器链chain;
- 如果chain为空,直接调用切点方法;
- chain不为空,将拦截器封装在ReflectiveMethodInvocation,并执行;
1.1.1通过Advisors中的Advice获取(包装为)MethodInterceptor拦截器链
getInterceptorsAndDynamicInterceptionAdvice
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
/**
* Determine whether the Advisors contain matching introductions.
*/
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
for (int i = 0; i < config.getAdvisors().length; i++) {
Advisor advisor = config.getAdvisors()[i];
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
(我们通过注解得到的Adivsor,中的Pointcut类型都是AspectJExpressionPointcut,其中的MethodMatchers.isRuntime()返回为false)
获取此方法的拦截器链,依然将Advisor分为了三种类型:
- PointcutAdvisor:当前class、method与Pointcut匹配时,才获取并保存MethodInterceptor的List;
- IntroductionAdvisor:当前class与Pointcut匹配时,获取并保存MethodInterceptor的List;
- 其他类型:直接获取并保存MethodInterceptor的List;
获取MethodInterceptor的方法:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
首先advisor.getAdvice()获取Advice。
如果是上篇中通过注解形式获取的Advisor,以@Before注解为例,那么此时得到的Advice应该是AspectJMethodBeforeAdvice。
进入的是interceptors.add(adapter.getInterceptor(advisor));这行代码,
将AspectJMethodBeforeAdvice包装成MethodInterceptor类型,并返回。
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
1.1.2拦截器链为空,直接调用当前方法
拦截器链为空,表示当前的Method并没有Advice逻辑需要增强
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
1.1.3拦截器链不为空
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
1.1.3.1 创建一个MethodInvocation(ReflectiveMethodInvocation)
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
创建一个ReflectiveMethodInvocation对象,注意这个类实现了MethodInvocation接口。
1.1.3.2 执行MethodInvocation.proceed
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这个proceed方法其实是通过递归,实现对当前Method的链式增强。
- 在这里记录了一个currentInterceptorIndex,当所有的Interceptor逻辑,即对于当前Method需要增强的Advice执行完后,就invokeJoinpoint通过反射调用原目标方法:
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
- 上文也说到,注解形式获取的PointCut都是静态的,所以if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher)返回为false。进入到else分支:
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
- 调用MethodInterceptor.invoke()方法。
以一个前置增强为例,那么实现类即为MethodBeforeAdviceInterceptor:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
- MethodBeforeAdvice.before(),不详细分析,是通过反射调用Advice中增强的逻辑;
- MethodInvocation.proceed() ,进入到下一个拦截点
那么AspectJAfterAdvice后置增强呢?只不过是先执行了proceed方法,再invoke原方法。
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
* 图解JDK AOP链式增强
1.2getProxy:返回代理类
其getProxy(classLoader)创建代理方法:
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
1.2.1寻找目标类上的接口
public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
if (addSpringProxy) {
proxiedInterfaces[specifiedInterfaces.length] = SpringProxy.class;
}
if (addAdvised) {
proxiedInterfaces[proxiedInterfaces.length - 1] = Advised.class;
}
return proxiedInterfaces;
}
方法中:
- 获取AdvisedSupport代理配置中,目标类中需要被代理的接口
在当前目标类中,如果需要被代理的接口数为0:- 如果目标类它自身就是个接口,将其加到目标Interface;
- 如果目标类本身已经是一个代理类(根据Proxy.isProxyClass判断),是JDK动态代理创建的代理对象,那么将其所有的接口都加到目标Interface;
- 重新获取目标接口
- addSpringProxy、addAdvised用于判断目标类是否是特殊接口:SpringProxy、Advised。一般情况下两个boolean都是true;
- 将目标代理类、SpringProxy、Advised三个接口填入proxiedInterfaces中,返回此数组。
1.2.2对equals和hashCode方法进行标记
用于在上述invoke中做特殊处理
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
for (Class<?> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Method method : methods) {
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
1.2.3Proxy.newProxyInstance
是反射包Proxy工具类中的创建proxy实例方法。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}