文章目录
3.Spring AOP的实现原理
3.2 链式调用
多个AOP 切面是如何叠加起作用的?
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
/**
* realSubject.request()是目标方法
* 在目标方法调用前、调用后、发生异常时,都需要被拦截
* aop是如何实现将这些调用串起来的?
*/
public void request() throws Exception{
//before
//记录调用次数
//权限控制,仅管理员可以操作
//开启事务
System.out.println("before:记录调用次数");
System.out.println("before:进行权限控制,仅管理员可以进行后续操作");
System.out.println("before:开启事务");
try {
realSubject.request();
} catch (Exception e) {
//afterThrowing
//事务失败,回滚操作
System.out.println("afterThrowing:事务失败,回滚操作 ex:" + e.getMessage());
throw e;
} finally {
//afterReturning
//事务成功,提交操作
System.out.println("afterReturning:事务成功,提交操作");
}
}
}
#3.2.1 职责链模式
3.2.1.1 V1
public abstract class Handler {
private Handler successor;
public Handler getSuccessor() {
return successor;
}
public void setSuccessor(Handler successor) {
this.successor = successor;
}
//对外暴露的方法
public void execute() {
handleProcess();
if (successor != null) {
successor.execute();
}
}
// 需要子类实现
protected abstract void handleProcess();
}
public class Client {
static class HandlerA extends Handler {
@Override
protected void handleProcess() {
System.out.println("handle by a");
}
}
static class HandlerB extends Handler {
@Override
protected void handleProcess() {
System.out.println("handle by b");
}
}
static class HandlerC extends Handler {
@Override
protected void handleProcess() {
System.out.println("handle by c");
}
}
//缺点:各个handler之间的顺序需要显式指定
//handlerA.setSuccessor(handlerB);
//handlerB.setSuccessor(handlerC);
public static void main(String[] args) {
HandlerA handlerA = new HandlerA();
HandlerB handlerB = new HandlerB();
HandlerC handlerC = new HandlerC();
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
handlerA.execute();
}
}
运行结果
handle by a
handle by b
handle by c
3.2.1.2 V2
public abstract class ChainHandler {
public void execute(Chain chain) {
handleProcess();
chain.proceed();
}
protected abstract void handleProcess();
}
public class Chain {
//将各个handler保存在handlers这个list中
//各个handler之间的执行顺序由chain来维持
private List<ChainHandler> handlers;
private int index = 0;
public Chain(List<ChainHandler> handlers) {
this.handlers = handlers;
}
public void proceed() {
if (index >= handlers.size()) {
return;
}
handlers.get(index++).execute(this);
}
}
public class ChainClient {
static class ChainHandlerA extends ChainHandler {
@Override
protected void handleProcess() {
System.out.println("handle by a");
}
}
static class ChainHandlerB extends ChainHandler {
@Override
protected void handleProcess() {
System.out.println("handle by b");
}
}
static class ChainHandlerC extends ChainHandler {
@Override
protected void handleProcess() {
System.out.println("handle by c");
}
}
public static void main(String[] args) {
/**
在list中的顺序决定了handler的执行顺序
*/
List<ChainHandler> handlers = Arrays.asList(
new ChainHandlerA(),
new ChainHandlerB(),
new ChainHandlerC()
);
Chain chain = new Chain(handlers);
chain.proceed();
}
}
运行结果
handle by a
handle by b
handle by c
3.2.2 Spring内部实现
以JDK动态代理为例,调用目标对象的方法时,实际上调用的是代理对象的invoke方法。
JdkDynamicAopProxy的invoke方法
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@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]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else 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);
}
}
}
JdkDynamicAopProxy的invoke方法核心代码如下:
//1).得到目标方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//2). 调用拦截器链
//如果chain是空的,直接调用target对象的method
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
//如果chain不是空的,进行拦截器链的调用
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
1)拦截器链是如何生成的
我们顺着this.advised.getInterceptorsAndDynamicInterceptionAdvice往下走。
/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
上面的this.advisorChainFactory其实是DefaultAdvisorChainFactory。
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@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();
//遍历config.getAdvisors
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//调用registry.getInterceptors得到advisor的MethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//调用pointcutAdvisor.getPointcut().getMethodMatcher()得到pointcut的MethodMatcher
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//调用interceptorList.add将拦截器加入到拦截器链中
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;
}
}
List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass)
其实这里的config就是ProxyFactoryBean的实例。(config传入了个AdvisedSupport实例,ProxyFactoryBean继承了AdvisedSupport)
继续找ProxyFactoryBean的代码。
ProxyFactoryBean的getObject方法调用时,会对adviceChain进行初始化(如果未初始化的话)。
@Override
public Object getObject() throws BeansException {
//adviceChain拦截器链的初始化
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
initializeAdvisorChain的内部实现:
因为ProxyFactoryBean实现了BeanFactoryAware接口,因此可以拿到当前的容器实例beanFactory。
通过调用this.beanFactory.get(beanName)方法将各个advice bean拿出来,然后加入到list中。
initializeAdvisorChain的具体内部实现如下。
/**
* Create the advisor (interceptor) chain. Advisors that are sourced
* from a BeanFactory will be refreshed each time a new prototype instance
* is added. Interceptors added programmatically through the factory API
* are unaffected by such changes.
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
this.advisorChainInitialized = true;
}
总结,在ProxyFactoryBean的getObject方法中,会初始化拦截器链,相关的bean是通过调用beanFactory.get(beanName)方法得到的。
2)拦截器链是如何链式调用的
ReflectiveMethodInvocation.proceed执行拦截器链的调用。
下面摘录了ReflectiveMethodInvocation的部分代码。
//ReflectiveMethodInvocation实现了接口ProxyMethodInvocation,而ProxyMethodInvocation是MethodInvocation的子接口。
//因此,ReflectiveMethodInvocation实现了MethodInvocation接口。
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final Object proxy;
protected final Object target;
protected final Method method;
protected Object[] arguments;
private final Class<?> targetClass;
/**
* List of MethodInterceptor and InterceptorAndDynamicMethodMatcher
* that need dynamic checks.
*/
//拦截器列表
protected final List<?> interceptorsAndDynamicMethodMatchers;
/**
* Index from 0 of the current interceptor we're invoking.
* -1 until we invoke: then the current interceptor.
*/
private int currentInterceptorIndex = -1;
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//如果拦截器list到了最后了,运行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//根据currentInterceptorIndex得到list中的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//1.如果拦截器中不仅有Interceptor,还需要进行动态方法匹配DynamicMethodMatcher
//InterceptorAndDynamicMethodMatcher包含了Interceptor和DynamicMethodMatcher,
//其中DynamicMethodMatcher用于运行时检查,用于在运行时判断方法是否需要拦截
//(说明:MethodMatcher方法匹配分静态和动态两种
//个人理解:
//静态检查:比如你要拦截的方法名是精确的,就是某个类的某个方法,可以在程序非运行时,就可判断是否需要拦截
//动态检查:比如你要拦截的某个方法,且要求入参为“aaa”,这种肯定需要运行时判断)
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
//1.1 如果匹配上了,调用interceptor的invoke方法
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//如果匹配上了,调用拦截器方法
//注意:interceptor.invoke(this)传入的是this。
//而ReflectiveMethodInvocation实现了MethodInvocation接口
//因此,传入的是一个MethodInvocation实例。
return dm.interceptor.invoke(this);
}
//1.2 如果没有匹配上,
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
//2. 如果拦截器就是个interceptor,调用invoker方法
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);
}
}
}
public interface MethodInterceptor extends Interceptor {
/**
* Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
* like to invoke {@link Joinpoint#proceed()}.
* @param invocation the method invocation joinpoint
* @return the result of the call to {@link Joinpoint#proceed();
* might be intercepted by the interceptor
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
Object invoke(MethodInvocation invocation) throws Throwable;
}
MethodBeforeAdviceInterceptor:会在目标方法运行之前进行拦截。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
AfterReturningAdviceInterceptor:会在目标方法返回后进行拦截
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
3)Spring使用职责链模式实现拦截器链链式调用
将上面调用拦截器链的简化下,如下。
public interface MethodInterceptor {
Object invoke(MethodInvocation mi);
}
public class MethodBeforeInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation mi) {
before();
return mi.proceed();
}
private void before() {
System.out.println("Method before");
}
}
public class AfterReturningInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation mi) {
Object retVal = mi.proceed();
afterReturning();
return retVal;
}
private void afterReturning() {
System.out.println("afterReturning");
}
}
public interface MethodInvocation {
Object proceed();
}
public class ReflectiveMethodInvocation implements MethodInvocation{
private List<MethodInterceptor> interceptors;
public ReflectiveMethodInvocation(List<MethodInterceptor> interceptors) {
this.interceptors = interceptors;
}
private int currentInterceptorIndex = -1;
public Object proceed() {
if (currentInterceptorIndex == interceptors.size() - 1) {
System.out.println("invoke target method");
return "obj after invoke target method";
}
return interceptors.get(++currentInterceptorIndex).invoke(this);
}
}
public class Client {
public static void main(String[] args) {
List<MethodInterceptor> interceptors = Arrays.asList(
new AfterReturningInterceptor(),
new MethodBeforeInterceptor()
);
ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(interceptors);
invocation.proceed();
}
}
结果如下
Method before
invoke target method
afterReturning
运行结果与List中interceptor的顺序有关吗?
把new AfterReturningInterceptor()和new MethodBeforeInterceptor()换下顺序,结果会不同吗?
答案:无关,不会。
4. ProxyFactory实现AOP
通过配置的方式使用AOP时,是通过ProxyFactoryBean的getObject()方法得到代理对象的。
Spring 提供ProxyFactory类,可以通过编写代码的方式创建代理对象。
TargetImpl target = new TargetImpl();
ProxyFactory proxyFactory = new ProxyFactory(target);
proxyFactory.addAdvisor(yourAdvisor);
proxyFactory.addAdvice(yourAdvice);
TargetImpl targetProxy = (TargetImpl)proxyFactory.getProxy();
ProxyFactory类提供的方法如下。
/**
* Factory for AOP proxies for programmatic use, rather than via a bean
* factory. This class provides a simple way of obtaining and configuring
* AOP proxies in code.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
* @since 14.03.2003
*/
@SuppressWarnings("serial")
public class ProxyFactory extends ProxyCreatorSupport {
/**
* Create a new ProxyFactory.
*/
public ProxyFactory() {
}
public ProxyFactory(Object target) {
setTarget(target);
setInterfaces(ClassUtils.getAllInterfaces(target));
}
public ProxyFactory(Class<?>... proxyInterfaces) {
setInterfaces(proxyInterfaces);
}
public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) {
addInterface(proxyInterface);
addAdvice(interceptor);
}
public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) {
addInterface(proxyInterface);
setTargetSource(targetSource);
}
public Object getProxy() {
return createAopProxy().getProxy();
}
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
}
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
}
public static Object getProxy(TargetSource targetSource) {
if (targetSource.getTargetClass() == null) {
throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
proxyFactory.setProxyTargetClass(true);
return proxyFactory.getProxy();
}
}