Aop原理分析

  • EnableAspectJAutoProxy注解开启Aop的时候会往容器中注册一个AnnotationAwareAspectJAutoProxyCreator 后置处理器,生成的代理对象都是由他完成。

  • 在实例化bean完成之后会进行初始化(这里的初始化是指给生成的bean进行属性赋值等操作)。
    (AbstractAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator的超类)

如果有不懂或者错误的地方欢迎各位大佬留言,看看哪里有需要改动或者讲解的。谢谢各位

流程:
1.先取出容器中所有的BeanClass。
2.遍历所有的BeanClass问那个是切面。
3.找到切面后再分别取出切面的所有通知方法。(有可能有多个切面)
4.遍历完以后将切面名称放入切面名称集合中后面再调用的时候就不要再去遍历。
5.这样我们就取出所有的通知方法,然后看bean是否有匹配的。
6.如果有匹配的就代表有可用的通知放方法。
7.使用Cligb代理创建对象(东西太多这里不予讲解),并且设置回调DynamicAdvisedInterceptor的intercept()方法。到时候调目标方法的时候会调用intercept()方法
8.intercept()会取出所有通知方法拦截器然后调用proceed()再执行拦截器的invoke()方法,
invoke()会再调proceed()有点递归的意思。里面可以理解成按拦截器的顺序来执行(例如MethodBeforeAdviceInterceptor方法前通知拦截器)

//简单的分析一下流程
AbstractAutowireCapableBeanFactory#initializeBean() -> 
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization() ->
AbstractAutoProxyCreator#postProcessAfterInitialization() ->
AbstractAutoProxyCreator#wrapIfNecessary()

贴出几个重要的方法让大家好理解。

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;
		}
		// 查询bean可用的通知方法
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			//如果查到了,将bean置为增强bean
			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;
	}
/**
	 *查询bean能使用的通知方法,没有返回null。
	 */
	@Override
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

	/**
	 * 寻找可用的通知方法
	 */
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//寻找所有的Advisors,一个通知方法一个Advisor
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//在所有的Advisors,看是否有beanClass匹配的
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		//添加ExposeInvocationInterceptor(暴露方法调用拦截器):暴露方法,后面递归把调用目标方法暴露给其他通知方法
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
/**
	 * 寻找所有Advisors。<br/>
	 *    1.容器中类型为Advisors的.<br/>
	 *    2.是切面的。<br/>
	 * @return
	 */
	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}
/**
	 * 创建并返回所有切面的Advisors。第一次进来的时候就把所有的切面找出来了<br/>
	 *    1.遍历所有的beanDefinitionNames。<br/>
	 *    2.再判断类有没有@Aspect注解,如果有就代表是切面。<br/>
	 *    3.再找出切面的通知方法,放入集合。<br/>
	 *    4.遍历完所有的beanDefinitionNames,就把集合中的通知方法返回出去。<br/>
	 */
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new LinkedList<Advisor>();
					aspectNames = new LinkedList<String>();
					//取出所有的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						//判断该类是不是切面
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								//找出切面的通知方法
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									//将Advisors放入缓存中
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new LinkedList<Advisor>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值