AOP Bean定义加载——AopNamespaceHandler处理流程 回到ConfigBeanDefinitionParser的parseAspect方法:
private void parseAspect(Element aspectElement, ParserContext parserContext) {
...
AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {
parsePointcut(pointcutElement, parserContext);
}
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
省略号部分表示是解析的是、这种标签,上部分已经说过了,就不说了,下面看一下解析部分的源码。
第5行~第7行的代码构建了一个Aspect标签组件定义,并将Apsect标签组件定义推到ParseContext即解析工具上下文中,这部分代码不是关键。
第9行的代码拿到所有下的pointcut标签,进行遍历,由parsePointcut方法进行处理:
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));
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
第2行~第3行的代码获取标签下的”id”属性与”expression”属性。
第8行的代码推送一个PointcutEntry,表示当前Spring上下文正在解析Pointcut标签。
第9行的代码创建Pointcut的Bean定义,之后再看,先把其他方法都看一下。
第10行的代码不管它,最终从NullSourceExtractor的extractSource方法获取Source,就是个null。
第12行~第18行的代码用于注册获取到的Bean定义,默认pointcutBeanName为标签中定义的id属性:
如果标签中配置了id属性就执行的是第13行第15行的代码,pointcutBeanName=id 如果标签中没有配置id属性就执行的是第16行第18行的代码,和Bean不配置id属性一样的规则,pointcutBeanName=org.springframework.aop.aspectj.AspectJExpressionPointcut#序号(从0开始累加) 第20行~第21行的代码向解析工具上下文中注册一个Pointcut组件定义
第23行~第25行的代码,finally块在标签解析完毕后,让之前推送至栈顶的PointcutEntry出栈,表示此次标签解析完毕。
最后回头来一下第9行代码createPointcutDefinition的实现,比较简单:
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;
}
关键就是注意一下两点:
标签对应解析出来的BeanDefinition是RootBeanDefinition,且RootBenaDefinitoin中的Class是org.springframework.aop.aspectj.AspectJExpressionPointcut 标签对应的Bean是prototype即原型的 这样一个流程下来,就解析了标签中的内容并将之转换为RootBeanDefintion存储在Spring容器中。
上篇文章说了,org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator这个类是Spring提供给开发者的AOP的核心类,就是AspectJAwareAdvisorAutoProxyCreator完成了【类/接口–>代理】的转换过程,首先我们看一下AspectJAwareAdvisorAutoProxyCreator的层次结构:
这里最值得注意的一点是最左下角的那个方框,我用几句话总结一下:
AspectJAwareAdvisorAutoProxyCreator是BeanPostProcessor接口的实现类 postProcessBeforeInitialization方法与postProcessAfterInitialization方法实现在父类AbstractAutoProxyCreator中 postProcessBeforeInitialization方法是一个空实现 逻辑代码在postProcessAfterInitialization方法中 基于以上的分析,将Bean生成代理的时机已经一目了然了:在每个Bean初始化之后,如果需要,调用AspectJAwareAdvisorAutoProxyCreator中的postProcessBeforeInitialization为Bean生成代理。
代理对象实例化—-判断是否为生成代理 上文分析了Bean生成代理的时机是在每个Bean初始化之后,下面把代码定位到Bean初始化之后,先是AbstractAutowireCapableBeanFactory的initializeBean方法进行初始化:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
初始化之前是第16行的applyBeanPostProcessorsBeforeInitialization方法,初始化之后即29行的applyBeanPostProcessorsAfterInitialization方法:
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;
}
这里调用每个BeanPostProcessor的postProcessBeforeInitialization方法。按照之前的分析,看一下AbstractAutoProxyCreator的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;
}
跟一下第5行的方法wrapIfNecessary:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (this.nonAdvisedBeans.contains(cacheKey)) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.add(cacheKey);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
第2行~第11行是一些不需要生成代理的场景判断,这里略过。首先我们要思考的第一个问题是:哪些目标对象需要生成代理?因为配置文件里面有很多Bean,肯定不能对每个Bean都生成代理,因此需要一套规则判断Bean是不是需要生成代理,这套规则就是第14行的代码getAdvicesAndAdvisorsForBean:
protected List < Advisor > findEligibleAdvisors(Class beanClass, String beanName) {
List < Advisor > candidateAdvisors = findCandidateAdvisors();
List < Advisor > eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
顾名思义,方法的意思是为指定class寻找合适的Advisor。
第2行代码,寻找候选Advisors,根据上文的配置文件,有两个候选Advisor,分别是节点下的和这两个,这两个在XML解析的时候已经被转换生成了RootBeanDefinition。
跳过第3行的代码,先看下第4行的代码extendAdvisors方法,之后再重点看一下第3行的代码。第4行的代码extendAdvisors方法作用是向候选Advisor链的开头(也就是List.get(0)的位置)添加一个org.springframework.aop.support.DefaultPointcutAdvisor。
第3行代码,根据候选Advisors,寻找可以使用的Advisor,跟一下方法实现:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
整个方法的主要判断都围绕canApply展开方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
第一个参数advisor的实际类型是AspectJPointcutAdvisor,它是PointcutAdvisor的子类,因此执行第7行的方法:
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
这个方法其实就是拿当前Advisor对应的expression做了两层判断:
目标类必须满足expression的匹配规则 目标类中的方法必须满足expression的匹配规则,当然这里方法不是全部需要满足expression的匹配规则,有一个方法满足即可 如果以上两条都满足,那么容器则会判断该满足条件,需要被生成代理对象,具体方式为返回一个数组对象,该数组对象中存储的是对应的Advisor。
没有回复内容