spring源码解读-第二部分面想切面编程

这是第二部分了。看这部分源码需要第一部分基础。但是不知道也没关系。spring在代码耦合上控制的很好。

先进行知识扫盲:
JoinPoint :
大白话:就是你的bean里面的方法;一个类里面有多少个方法(公共的)就有多少个JoinPoint,只是一个定义,方便进行表达沟通。比如说人家问你JoinPoint是什么,你就说:是xxx类的xx方法;
专业解释:系统中的执行点。不同的规范中可能有不同类型的执行点(方法调用,方法执行,构造器,属性赋值等等,不要记费神);Spring中只支持方法执行级别的执行点;
切面:
Pointcut:切入点,用这个就是定义了一个或者一批joinPoint。然后可以通过织入的动作把增强逻辑加入到这些执行点上面;
Advice:增强逻辑,就是一段你写的代码;然后分为前置增强,后置增强,环绕增强;
Aspect:切面,Pointcut和Advice共同组成切面。
通知、增强处理(Advice) 就是你想要的功能,也就是上说的安全、事物、日子等。你给先定义好,然后再想用的地方用一下。包含Aspect的一段处理代码
Weaving:织入,代表一个操作,就是把切面加到切点上,生成一个带有切面逻辑的代理的操作;

动态代理和CGLIB(作者发现spring在源码中已经包含了cglib代码在org.springframework.cglib中,所以不需要再单独引入了)代理的知识你自己查查呗。知道代理模式和如何使用就可以了。

下面说说思想然后再去看源码;
spring织入aop逻辑可以通过手动编码,配置文件,注解等多种方式。

还记得第一部分,spring在出现循环依赖的时候,需要对bean进行提前代理。那么我们就先去看这部分代码;
路标1: getEarlyBeanReference;
看过第一部分的源码解析之后,你应该能在半分钟内找到下面的代码。不然说明你还需要努力;
我们看到这里是通过接口SmartInstantiationAwareBeanPostProcessor来实现来对bean进行加工的。那么这个BeanPostProcessor是在啥时候注册的呢?这个问题留给你去探索一下。其实这个问题应该在第一部分就讲解的;但是留给你探索有助于你加深印象。

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
					if (exposedObject == null) {
						return exposedObject;
					}
				}
			}
		}
		return exposedObject;
	}

路标2:ibp.getEarlyBeanReference(exposedObject, beanName)

	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		//取一个缓存用的key:beanClass.getName() + "_" + beanName
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.add(cacheKey);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

路标3:wrapIfNecessary(bean, beanName, cacheKey)

	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.获取这个bean命中的切面列表
		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;
	}

路标4:createProxy
这里就是给bean创建代理的地方了,会根据你配置的切面信息进行织入,然后返回一个完成的代理对象

	protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	} 

这是提前代理的地方,那么正常生命周期的bean在哪里代理呢?先告诉你答案,肯定是在实例化完成之后。那么我们是去找初始化那部分代码。半分钟内能找到吗?

路标doCreateBean->initializeBean ->applyBeanPostProcessorsAfterInitialization;
就在这里的时候进行处理的;你可能说这里也看不出来啥啊?是的。但是别忘了上面那种情况就是beanPostProcess来干活的。那么那个postProcess这里是不是也可以取到,先告诉你一个实现,剩下的你自己研究下AnnotationAwareAspectJAutoProxyCreator

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

看下AnnotationAwareAspectJAutoProxyCreator中的逻辑

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

上面问题的提醒:refresh()->registerBeanPostProcessors();但是这里并没有找到相关信息。却可以看到这里有通过容器去加载BeanPostProcessors对应的bean.那么你可以想一下。各种开启aop的方式,从那里找找看能不能找到什么线索!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值