1. 简介
AOP说简单点就是通过代理对代码进行一个封装,那要理解AOP就是要解决下面三个问题:
- 在IOC的创建bean的流程中,在哪里执行了代理操作?
- 配置在xml中的< aop:config >, < aop:aspectj-autoproxy/ > 等aop标签是怎么被解析的?
- 执行原始方法的过程中,怎么触发@before之类的advice方法。
围绕上述三个问题,我们从注册,代理,执行三方面来看看AOP到底是怎么实现的。
2. 几个概念
spring aop 中有很多概念,有的在代码中是具体实现的,有的没有,所以在这里做一个说明,方便后面的阅读。
- advice方法:表示被@before等 注解的方法
- advice:在spring中是有具体的advice实现的,用来封装advice方法。每个advice里面都有一个Method对象,就是advice方法。
- advisor:封装advice和pointcut一对一的关系。每个advisor里面都包含了一个pointcut和一个advice。
- aspect:在spring中只是一个概念,advisor可以理解为它具体的实现。
3. 注册AOP相关BeanDefinition
注册BeanDefinition属于IOC的内容,就不细讲了。这里从获取aop名称空间对应的handler开始说。
3.1 解析入口
aop是自定义的名称空间,所以delegate.parseCustomElement(ele)就是解析的入口。
// DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析bean等默认名称空间的标签
parseDefaultElement(ele, delegate);
}
else {
// ***使用自定义元素解析,入口。***
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
3.2 获得handler
获得aop的handler :AopNamespaceHandler
// BeanDefinitionParserDelegate
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// "http://www.springframework.org/schema/aop"
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// AopNamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
//...
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
3.3 开始解析
获得对应< aop:config >的parser,开始解析。
// ConfigBeanDefinitionParser
// 对应<aop:config>的parser
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 注册org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator
// 并把proxy-target-class和expose-proxy属性设置进去
configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
// 解析pointcut
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
// 解析advisor
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
// 解析aspect
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
主要干两件事情:
- 注册一个AspectJAwareAdvisorAutoProxyCreator,这就是用来创建代理的,具体后面说。
- 解析xml中的各种aop配置,把它们变成beanDefinition,注册到beanFactory里面。
接下去对parseAspect进行分析,因为parsePointcut和parseAdvisor在parseAspect中都会涉及到。
3.4 parseAspect
// ConfigBeanDefinitionParser
private void parseAspect(Element aspectElement, ParserContext parserContext) {
String aspectId = aspectElement.getAttribute(ID);
String aspectName = aspectElement.getAttribute(REF);
try {
//...
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
// 检查是不是Advice,就是Before,After,Around那五个
if (isAdviceNode(node, parserContext)) {
// ...
// 解析Advice
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
//...
// 解析pointcut
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {
parsePointcut(pointcutElement, parserContext);
}
// ...
}
finally {
this.parseState.pop();
}
}
上面的代码主要完成了两件事情:
- 解析advice,并把其中的方法method和对应pointcut组合起来,变成一个advisor。
- 解析pointcut。
上述两个步骤的目的就是把advisor和pointcut的beanDefinition注册到beanFactory中。接下去就详细说明1和2的具体过程。
3.4.1 parseAdvice
// ConfigBeanDefinitionParser
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
// 定义一个advice方法的bean。
// 通过MethodLocatingFactoryBean返回一个类型为Method的bean。
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
// aspect的类名
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
// advice方法名
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
// 表示非用户创建的
methodDefinition.setSynthetic(true);
// 创建切面类 的bean
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// 创建advice的BeanDefinition
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);
// 创建advisor
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// 注册advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
// ConfigBeanDefinitionParser
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
// 获取对应的Advice类,比如org.springframework.aop.aspectj.AspectJMethodBeforeAdvice
// 创建RootBeanDefinition
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
// 加入returningName
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
// 加入throwingName
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
// 加入argumentNames
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
// 加入具体的advice方法作为构造函数的第一个参数
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
// 加入pointcut作为构造函数的第二个参数
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
// 加入aspect作为第三个参数
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
return adviceDefinition;
}
3.4.2 parsePointcut
// ConfigBeanDefinitionParser
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
String id = pointcutElement.getAttribute(ID);
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
// 创建AspectJExpressionPointcut.class的bd
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
// 注册bd
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
// ...
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
// ConfigBeanDefinitionParser
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
总结
解析< aop:config >总体流程:
-
找到AopNamespaceHandler,找到里面的ConfigBeanDefinitionParser
-
ConfigBeanDefinitionParser主要干两件事情:1. 注册AutoProxyCreator,2. 解析aspect
-
aspect解析过程如下:(bd=beanDefinition)
3.1 解析advice,这个过程中需要用到advice方法所在类的工厂bd,advice方法的工厂bd,对应Pointcut的bd。最终生成一个AspectJPointcutAdvisor,只注册这个AspectJPointcutAdvisor的bd。
3.2 解析并注册pointcut的bd。pointcut是原型的,非singleton。
4. 代理
在注册BeanDefinition过程中提到了AspectJAwareAdvisorAutoProxyCreator,这个类就是实现代理的核心,它实际上是一个BeanPostProcessor。所以代理的时机就是bean初始化完成之后。
4.1 代理开始postProcessAfterInitialization
// AbstractAutoProxyCreator
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 创建代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 是否是基础类(Advice,Pointcut等类)或者需要跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获得当前bean需要的advice或者Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
从上面的代码可以看出代理就是两个步骤:
- 获取所有合适的advisor。
- 创建proxy对象。
接下去从这两方面进行详细分析。
4.2 获取所有合适的advisor
// AbstractAdvisorAutoProxyCreator
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 找到合适的Advisors
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获得所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 在所有Advisor中挑可用于当前bean的,需要符合下面的要求
// 1. IntroductionAdvisor按类匹配
// 2. PointcutAdvisor按方法匹配,bean中的方法至少有一个满足advisor的要求
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors,
beanClass, beanName);
// 在eligibleAdvisors的第0个位置加一个ExposeInvocationInterceptor,把MethodInvocation放到一个自己的threadlocal里面,getjoinPoint的时候会用到
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
找所有的advisor
// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 根据Advisor类,找到所有的bean
return this.advisorRetrievalHelper.findAdvisorBeans();
}
4.3 创建代理
// AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建proxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 根据proxy-target-class,当前bean有没有实现接口等决定要不要用cglib代理。
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// specificInterceptors里面可能有advice,把它变成advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 把advisors写进proxyFactory,后续proxyFactory会被传入AopProxy
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 获取代理
return proxyFactory.getProxy(getProxyClassLoader());
}
// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
// ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
//DefaultAopProxyFactory
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);
}
// 用cglib,这个config是一个proxyFactory,里面存了匹配的advisors
return new ObjenesisCglibAopProxy(config);
}
else {
// 用jdk
return new JdkDynamicAopProxy(config);
}
}
总结
代理过程主要分成两部分:
- 获得所有当前bean可用的advisor
1.1 按类型找到所有的advisor。
1.2 用advisor中的pointcut决定当前bean需要用到哪些advisor。具体规则在代码的注释中。 - 创建proxy
2.1 创建proxyFacotory,写入上一步找到的advisors
2.2 决定用cglib还是jdk的proxy: proxy-target-class为true强制用CGLIB,否则默认用JDK PROXY,如果没有接口,用CGLIB。
2.3 用proxyFacotory创建ObjenesisCglibAopProxy或者JdkDynamicAopProxy,会把proxyFacotory作为参数传入,这样AopProxy就能得到advisors了。
2.4 从JdkDynamicAopProxy或者ObjenesisCglibAopProxy中获得proxy,这些就主要是代理的知识了。
5. 执行
只分析用JdkDynamicAopProxy进行代理的情况。
5.1 入口:invoke
重点就是invocation.proceed()。
// JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// ...
Object retVal;
// 暴露Proxy,实现类内调用时使用代理
// 如果不设置exposeProxy,类内一个方法调用另一个方法是执行原生方法的
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获得匹配当前方法的Interceptor链,如果advisor实现了MethodInterceptor,
// 直接返回,否则取出其中的advice,包装成MethodInterceptor,返回。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// 执行原始方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 根据interceptor链创建MethodInvocation
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// ***重点:开始执行interceptor链***
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// 返回this
retVal = proxy;
}
// ...
}
return retVal;
}
finally {
// ...
}
上面的代码主要干三件事情:
- 如果需要的话,暴露当前的proxy
- 获取当前方法需要的所有advisor并转换成interceptor,组成一个interceptor链chain。
- 根据chain,创建MethodInvocation ,通过invocation.proceed执行interceptor链。
接下去详细分析invocation.proceed。
5.2 proceed
这个地方会比较绕,先明确一点,这个方法的调用者是invocation,一个MethodInvocation的对象。
// ReflectiveMethodInvocation
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 说明所有的interceptor都执行完了,接下去可以执行原始的方法了。
return invokeJoinpoint();
}
// 先++currentInterceptorIndex,然后获取即将要执行的interceptor
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;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, 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 {
// 执行interceptor,注意传入的参数this!
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
重点就是最后一行代码,主要传入的参数:this,这个很重要。
以一个使用了@before和@after的bean为例子,具体分析一下。
此时需要执行的interceptor chain里面包含三个interceptor:
- ExposeInvocationInterceptor
- MethodBeforeAdviceInterceptor
- AspectJAfterAdvice
先执行ExposeInvocationInterceptor
// ExposeInvocationInterceptor
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
// 暴露当前的MethodInvocation
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
此时传入了一个MethodInvocation,这个就是调用5.2 proceed方法的MethodInvocation。重点就是return mi.proceed(),这个方法不就又跳回到5.2了吗?
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
这时候currentInterceptorIndex就会+1,就得到了下一个interceptor:MethodBeforeAdviceInterceptor
执行MethodBeforeAdviceInterceptor
// MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
// 调用@before方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 这一步调用其实又回到了ReflectiveMethodInvocation的proceed,就是上面的那个函数。
return mi.proceed();
}
同理,最后return mi.proceed();又会回到5.2的proceed
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
此时得到的就是AspectJAfterAdvice。
执行AspectJAfterAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
它会先执行proceed,然后再执行after的代码。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 说明所有的interceptor都执行完了,接下去可以执行原始的方法了。
return invokeJoinpoint();
}
现在就是if中的情况了,所有的interceptor都执行完毕,可以执行原始的方法了。
总结
执行方法过程如下:
首先调用JdkDynamicAopProxy中的invoke方法
- 如果需要的话,暴露当前的proxy
- 获取当前方法需要的所有advisor并转换成interceptor,组成一个interceptor链chain。
- 根据chain,创建MethodInvocation ,通过invocation.proceed执行interceptor链。
然后调用MethodInvocation的proceed,它会按顺序调用interceptor,interceptor内部又会调用MethodInvocation的proceed,就是一个递归的过程。
6. aop:aspectj-autoproxy 注解方式
注解方法跟上述过程其实差不多,也是这三部分,主要区别是以下两点:
- 注册过程中不需要去解析advisor了,用到的parser是AspectJAutoProxyBeanDefinitionParser。注册进去的AutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator。
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 就是注册了一个AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
- 那么问题来了,advisor的定义是在哪里注册进去的呢?
4.2中有一步是获取所有的advisor,在AnnotationAwareAspectJAutoProxyCreator中,它的实现如下。
// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
// 调用父类的方法,也就是上面的那个方法。
// 从所有的beanDefinition中找Advisor类的,然后得到对应的bean。
List<Advisor> advisors = super.findCandidateAdvisors();
// 找到所有带@Aspect注解的类,然后根据@before等五个advice方法去生成Advisor,中间会解析pointcut
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
先调用父类的方法,然后再根据注解去解析,然后直接创建对应的advice,pointcut,advisor就好了。
7.怎样会调用postProcessBeforeInstantiation进行代理
不知道什么场景下会用到。只从代码上分析可以调用的情况。
下面的getCustomTargetSource是关键
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
// ******关键代码*****
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
// 默认是空的
// AbstractAutoProxyCreator
private TargetSourceCreator[] customTargetSourceCreators;
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// We can't create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
// 遍历customTargetSourceCreators找一个可以产生TargetSource的
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
// Found a matching TargetSource.
if (logger.isTraceEnabled()) {
logger.trace("TargetSourceCreator [" + tsc +
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
}
}
// No custom TargetSource found.
return null;
}
需要往TargetSourceCreator数组里面传一些自己定义的TargetSourceCreator,然后在解析beanDefinition的时候不要用默认的ProxyCreator,自己在xml文件中配一个,名字如下。
// AopConfigUtils
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
这样在解析<aop:config>的时候就会用我们自己的定义的ProxyCreator,而不是去建一个默认的beanDefinition