一、概述

在Spring AOP 中:

  • AnnotationAwareAspectJAutoProxyCreator是基于Bean中的AspectJ 注解来实现自动代理,在Bean创建的过程中完成对切入点的增强。
  • Spring AOP 的其他实现方式可以查看 【Spring】 AOP Base

对于 Spring AOP 使用注解的方式中,我们配置开启AOP注解

  • 可以用XML的方式:
<!-- 自动生成代理  底层就是AnnotationAwareAspectJAutoProxyCreator -->
<aop:aspectj-autoproxy />
  • 或者用注解的方式 在配置类上标注 @EnableAspectJAutoProxy 注解
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
//业务逻辑类加入容器中
@Bean
public UserDao userDao(){
return new UserDao();
}
//切面类加入到容器中
@Bean
public MyAspect myAspect(){
return new MyAspect();
}
}
  • 无论是XML 还是@EnableAspectJAutoProxy 底层实现都是AnnotationAwareAspectJAutoProxyCreator

二、@EnableAspectJAutoProxy 注解分析

此注解的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
...
}

  点击此注解发现 有一个@Import注解,此注解是将其中的类直接导入到Spring 容器中,再看AspectJAutoProxyRegistrar 这个类,这个类是一个注册器,我们可以通过此类手动注册bean到容器中,Spring 源码中将AnnotationAwareAspectJAutoProxyCreator通过Regist注册到了Spring容器当中关于@Import的一些总结查阅【Spring】 IOC Base初始化Bean方式的部分

  AspectJAutoProxyRegistrar类中,可以分析出internalAutoProxyCreator 就是AnnotationAwareAspectJAutoProxyCreator

三、分析AnnotationAwareAspectJAutoProxyCreator

接下来分析一下这个关键的类:
首先看AnnotationAwareAspectJAutoProxyCreator 的继承体系

  • AnnotationAwareAspectJAutoProxyCreator

    • -->AspectJAwareAdvisorAutoProxyCreator

      • -->AbstractAdvisorAutoProxyCreator

        • -->AbstractAutoProxyCreator

          • implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

可以分析出此类 实现了 BeanPostProcessorBeanFactoryAware 接口,所以说此类具有后置处理器的特性和Aware接口的特点

我们就可以从两方面来分析这个类的机制:

  1. 关注后置处理器(在bean初始化完成前后做事情)、
  2. 自动装配BeanFactory

四、执行流程

下面分析一下执行的流程:

1. registerBeanPostProcessors()

  在容器中注册AnnotationAwareAspectJAutoProxyCreator

第一步: 传入配置类,创建ioc容器
第二步: 注册配置类,调用 refresh() 刷新容器
第三步: registerBeanPostProcessors(beanFactory),注册bean的后置处理器来方便拦截bean的创建,步骤如下:
(第一步): 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor

(第二步): 给容器中加别的BeanPostProcessor
(第三步): 优先注册实现了PriorityOrdered接口的BeanPostProcessor;
(第四步): 再给容器中注册实现了Ordered接口的BeanPostProcessor;
(第五步): 注册没实现优先级接口的BeanPostProcessor;

这个方法的源码如下:

public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取ioc容器已经定义了的需要创建对象的所有后置处理器
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//对后置处理进行分类
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//首先注册实现了PriorityOrdered 接口的后置处理器
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//然后注册实现了Ordered接口的后置处理器
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
//注册常规的(即没有实现优先级接口)的后置处理器
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

internalAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator】 是实现了Ordered接口的后置处理器,注册的过程,实际上就是创建BeanPostProcessor对象,保存在容器中,方法的调用流程
getBean()--> doGetBean()--> getSingleton()-->最终走到了createBean()方法,


调用getBean()


在getBean中调用doGetBean


在doGetBean中调用getSingleton


getSingleton方法调用返回是nul


在doGetBean中开始调用createBean方法

在createBean方法中调用了doCreateBean方法,此方法的执行流程为:

  • 创建Bean的实例:
  • populateBean;给bean的各种属性赋值
  • initializeBean:初始化bean;在此方法中:
    • invokeAwareMethods():处理Aware接口的方法回调
    • applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
    • invokeInitMethods();执行自定义的初始化方法
    • applyBeanPostProcessorsAfterInitialization();执行后置处理器的postProcessAfterInitialization();
    • BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功; aspectJAdvisorsBuilder

(第六步): 把BeanPostProcessor注册到BeanFactory中;beanFactory.addBeanPostProcessor(postProcessor);

以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

2. finishBeanFactoryInitialization()

第四步: 执行finishBeanFactoryInitialization():完成BeanFactory初始化工作,创建剩下的单实例bean。

(第一步): 遍历获取容器中所有的Bean,依次创建对象getBean(beanName);
getBean->doGetBean()->getSingleton()->

(第二步): 创建bean

下面是doGetBean方法的部分源码

protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
//这里先尝试获取单实例bean
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
....
}else {
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//这里创建Bean实例
return createBean(beanName, mbd, args);
}
...
}
...
return (T) bean;
}
  • 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;只要创建好的Bean都会被缓存起来
  • createBean(),创建bean,下面是createBean方法的流程分析:

  • 1.resolveBeforeInstantiation(beanName, mbdToUse):希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续

    • 后置处理器先尝试返回对象;
    • bean = applyBeanPostProcessorsBeforeInstantiation():拿到所有后置处理器,如果是 InstantiationAwareBeanPostProcessor; 就执行postProcessBeforeInstantiation
    if (bean != null) {
    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    }
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
    //如果是这个类型的处理器,就执行其postProcessBeforeInstantiation() 方法
    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
    if (result != null) {
    return result;
    }
    }
    }
    return null;
    }
    • AnnotationAwareAspectJAutoProxyCreator会在任何bean创建之前先尝试返回bean的实例
    • BeanPostProcessor是在Bean对象创建完成初始化前后调用的
    • InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的
  • 2.doCreateBean(beanName, mbdToUse, args):真正的去创建一个bean实例,此方法的流程在上面已经介绍 (第三.(五)步中图片下面)

3. InstantiationAwareBeanPostProcessor后置处理器的执行逻辑

  经过上面的分析可以知道,在所有bean创建之前会有一个拦截:由于 AnnotationAwareAspectJAutoProxyCreator 是一个InstantiationAwareBeanPostProcessor 类型的后置处理器,它会调用postProcessBeforeInstantiation()方法

(一):每一个bean创建之前,调用postProcessBeforeInstantiation();
关注 业务逻辑类切面类的创建

  源码如下:

    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName); //1.判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
} //2.判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)
//3.是否需要跳过
//获取候选的增强器(切面里面的通知方法)
//【List<Advisor> candidateAdvisors】每一个封装的通知方法的
//增强器是 InstantiationModelAwarePointcutAdvisor类型;
//判断每一个增强器是否是 AspectJPointcutAdvisor 类型的,
//如果是,返回true;如果不是调用父类的【shouldSkip()-->永远返回false】
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.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
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;
}

(二):创建完业务类对象之后调用执行postProcessAfterInitialization

  源码如下:

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
} // Create proxy if we have advice.
/*1.获取当前bean的所有增强器(通知方法) getAdvicesAndAdvisorsForBean() 内部流程:
* 1.1找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
* 1.2获取到能在bean使用的增强器。
* 1.3给增强器排序
*/
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//2.保存当前bean在advisedBeans中;
this.advisedBeans.put(cacheKey, Boolean.TRUE); /*3. 如果当前bean需要增强,创建当前bean的代理对象;
* 1)、获取所有增强器(通知方法)
* 2)、保存到proxyFactory
* 3)、创建代理对象:Spring自动决定
* JdkDynamicAopProxy(config);jdk动态代理;
* ObjenesisCglibAopProxy(config);cglib的动态代理;
* 4)、给容器中返回当前组件增强了的代理对象;
* 5)、以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程;
*/
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;
}

4. 目标方法执行

  经过上面的流程后,容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程。


代理对象

  通过Debug的几次进入进出之后,可以进入到CglibAopProxy.intercept()方法,此方法用于拦截目标方法的执行

源码如下:

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
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 = getTarget();
if (target != null) {
targetClass = target.getClass();
} /*
* 1. 根据ProxyFactory对象获取将要执行的目标方法拦截器链;
* 方法源码见下面
* 1.1 List<Object> interceptorList保存所有拦截器 5
* 一个默认的ExposeInvocationInterceptor 和 4个增强器;
* 1.2 遍历所有的增强器,将其转为Interceptor;
* registry.getInterceptors(advisor);
* 1.2.1 将增强器转为List<MethodInterceptor>;
* 1.2.2 如果是MethodInterceptor,直接加入到集合中
* 1.2.3 如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
* 转换完成返回MethodInterceptor数组;
*/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
/*
* 2.如果没有拦截器链,直接执行目标方法;
* 拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
*/
// 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 = methodProxy.invoke(target, argsToUse);
}
else { /*
* 3. 如果有拦截器链,把需要执行的目标对象,目标方法,
* 拦截器链等信息传入,创建一个 CglibMethodInvocation 对象,
* 并调用Object retVal = mi.proceed();
*/
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

第一部分,得到拦截器链

上面源码 1 中调用的方法

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;
}

上面方法中调用了如下方法:

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. /**
* 1.1 List<Object> interceptorList保存所有拦截器 5
* 一个默认的ExposeInvocationInterceptor 和 4个增强器;
*/
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)) { /*
1.2 遍历所有的增强器,将其转为Interceptor;
*/
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;
}

上面方法又调用了如下方法:

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
/*
* 1.2.1 将增强器转为List<MethodInterceptor>;
* 1.2.2 如果是MethodInterceptor,直接加入到集合中,如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
* 1.2.3转换完成返回MethodInterceptor数组;
*/
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()]);
}

  经过上面中的 1 我们得到了拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)

第二部分,拦截器链的触发过程

上面源码 3 中调用的方法

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);
}
}
  • 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
  • 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
    • 拦截器链的机制,保证通知方法与目标方法的执行顺序;


链式调用

总结

  1. @EnableAspectJAutoProxy 开启AOP功能
  2. @EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
  4. 容器的创建流程:
    • registerBeanPostProcessors():注册后置处理器;创建AnnotationAwareAspectJAutoProxyCreator对象
    • finishBeanFactoryInitialization():初始化剩下的单实例bean
      • 创建业务逻辑组件和切面组件;
      • AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程;
      • 组件创建完之后,判断组件是否需要增强,如果需要增强:将切面的通知方法包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);
  5. 执行目标方法:代理对象执行目标方法
    • CglibAopProxy.intercept();

      • 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
      • 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
      • 效果:
        • 正常执行:前置通知-》目标方法-》后置通知-》返回通知
        • 出现异常:前置通知-》目标方法-》后置通知-》异常通知

【Spring】AOP注解方式实现机制的更多相关文章

  1. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  2. 转:Spring AOP 注解方式实现的一些“坑”

    使用过Spring AOP的注解方式实现,也入过不少坑,现在做一下记录,希望有同样需求的朋友可以少走弯路 使用之前还是先过一下官方文档吧,至少可以少走弯路,不用担心英文读不懂,其实只看代码例子就能理解 ...

  3. Spring Aop 注解方式参数传递

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  4. Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop

    Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...

  5. (转)使用Spring的注解方式实现AOP的细节

    http://blog.csdn.net/yerenyuan_pku/article/details/52879669 前面我们已经入门使用Spring的注解方式实现AOP了,现在我们再来学习使用Sp ...

  6. (转)使用Spring的注解方式实现AOP入门

    http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...

  7. 来一手 AOP 注解方式进行日志记录

    系统日志对于定位/排查问题的重要性不言而喻,相信许多开发和运维都深有体会. 通过日志追踪代码运行状况,模拟系统执行情况,并迅速定位代码/部署环境问题. 系统日志同样也是数据统计/建模的重要依据,通过分 ...

  8. Spring AOP配置方式

    AOP 面向切面编程,允许在 java 应用中的方法调用的前后做一些处理. 本文通过实例介绍两种主要的Spring AOP 配置方式:xml 方式配置,注解方式配置 XML 方式配置 1. 项目包类结 ...

  9. Spring AOP注解为什么失效?90%Java程序员不知道

    使用Spring Aop注解的时候,如@Transactional, @Cacheable等注解一般需要在类方法第一个入口的地方加,不然不会生效. 如下面几种场景 1.Controller直接调用Se ...

随机推荐

  1. MySQL操作命令梳理(2)

    一.表操作 在mysql运维操作中会经常使用到alter这个修改表的命令,alter tables允许修改一个现有表的结构,比如增加或删除列.创造或消去索引.改变现有列的类型.或重新命名列或表本身,也 ...

  2. Mysql无法启动情况下,如何恢复数据?

    本文适用于,mysql无法启动,但数据文件未丢失的情况. Mysql因意外情况,导致无法启动,数据库未做备份的情况下,如何将数据迁移至其他数据库中. 原数据库地址:192.168.1.100(以下简称 ...

  3. 19 个 JavaScript 编码小技巧

    这篇文章适合任何一位基于JavaScript开发的开发者.我写这篇文章主要涉及JavaScript中一些简写的代码,帮助大家更好理解一些JavaScript的基础.希望这些代码能从不同的角度帮助你更好 ...

  4. Oracle创建设置查询权限用户

    用户创建的可以参考博客: https://blog.csdn.net/u014427391/article/details/84889023 Oracle授权表权限给用户: 语法:grant [权限名 ...

  5. Oauth2认证模式之授权码模式实现

    Oauth2认证模式之授权码模式(authorization code) 本示例实现了Oauth2之授权码模式,授权码模式(authorization code)是功能最完整.流程最严密的授权模式.它 ...

  6. 关于Linux的简单介绍

    Linux: 诞生日期:1991年 开发者:林纳斯·托瓦茨 特点:免费,开源    发行版本:centos|red Hat|Ubuntu|红旗等    思想:一切都是文件 重要文件目录 bin:二进制 ...

  7. Java程序员备战“金九银十”必备的面试技巧(附携程Java岗面试题)

    一.面试前的准备 1.1 如何准备一场面试1.1.1 如何获取大厂面试机会1.1.2 面试必知 ①. 准备介绍自己 ②. 关于着装 ③ .随身带上自己的成绩单和简历 ④. 如果笔试就提前刷一些笔试题 ...

  8. 减谈迷宫C++

    今天老师让做了个迷宫问题,我一看到就发现和我之前写过的一个程序是一样 的,但是在后来编写的时候有一个地方搞错了,最后下课了我还是没有正确的编写好,然后今天回来之后自己有看了一下,现在已经解决了. #i ...

  9. (二十七)c#Winform自定义控件-多输入窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  10. ASP.NET Core MVC 之区域(Area)

    区域(Area)是一个 ASP.NET MVC 功能,用于将相关功能组织为一个单独的命名空间(用于路由)和文件结构(用于视图).使用区域通过向控制器和操作添加 一个路由参数(area)来创建用于路由目 ...