这里主要是使用org.springframework:spring-beans:5.2.0.RELEASE进行分析
文章目录
- ①. aspectj-autoproxy标签
- ②. aspectj-autoproxy标签解析
- ③. DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions方法
- ④. 通过parseCustomElement解析自定义标
- ⑤. Namespacehandler接口
- ⑥. 获取NamespaceHandler
- ⑦. AopNamespaceHandler的init方法
- ⑧. 通过NamespaceHandler的parse方法解析aspectj-autoproxy标签
- ⑨. AnnotationAwareAspectJAutoProxyCreator注册器分析
- ⑩. ``标签解析
- ⑪. AspectJAutoProxyBeanDefinitionParser 源码分析
1. 查看源码相关的快捷键
快捷键 | 作用 |
---|---|
Ctrl + Shift+i | 出现类似于预览的小窗口 |
Ctrl + Enter | (接上步)完全打开源码 |
Ctrl + 鼠标左键 | 一步到位打开源码 = Ctrl + Shift+i –>Ctrl + Enter |
Alt+7 | 查看类的有什么方法 |
ctrl+f12 | 查看继承方法 |
ctrl+h | 查看接口的实现类 |
alt+7 | 查看类的有什么方法 |
2下shift | 全局搜索整个项目 |
基于注解配置的属性源码分析
①. aspectj-autoproxy标签
使用注解方式应用aop需要在配置文件中配置aop:aspectj-autoproxy/, 而该标签有两个属性,proxy-target-class 和 expose-proxy。
1. proxy-target-class属性
如果被代理的目标对象至少实现了一个接口,则会使用JDK动态代理
,所有实现该目标类实现的接口都将被代理;如果该目标对象没有实现任何接口,则创建CGLIB动态代理
。但是可以通过proxy-target-class属性强制指定使用CGLIB代理。如果指定了proxy-target-class="true"
则将强制开启CGLIB动态代理。
2. expose-proxy属性
解决目标对象内部的自我调用无法实施切面增强的问题。
②. aspectj-autoproxy标签解析
分析一下Spring是如何解析自定义标签aspectj-autoproxy的。
自定义标签解析入口DefaultBeanDefinitionDocumentReader
③. DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions方法
DefaultBeanDefinitionDocumentReader类的parseBeanDefinitions方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 1、解析默认命名空间
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)) {
parseDefaultElement(ele, delegate);
}
// 自定义命名空间
else {
delegate.parseCustomElement(ele);
}
}
}
}
// 2、解析自定义命名空间
else {
delegate.parseCustomElement(root);
}
}
④. 通过parseCustomElement解析自定义标
通过parseCustomElement解析自定义标签
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 1、获取namespaceUri
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 2、根据namespaceUri得到命名空间解析器
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 2、使用命名空间解析器解析自定义标签
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
对自定义标签的解析交给了NamespaceHandler接口,如果我们想在Spring中实现自己的自定义标签,那么就需要实现NamespaceHandler接口,并通过重写其中的方法,来完成对自定义标签的解析。
⑤. Namespacehandler接口
Namespacehandler接口
⑥. 获取NamespaceHandler
获取NamespaceHandler
@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
// 1.获取所有的namespaceUri,NamespaceHandler键值对map集合并得到
// 当前namespaceUri对应的NamespaceHandler类
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
// 2、通过BeanUtils实例化NamespaceHandler
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//最后调用NamespaceHandler实例的init方法。
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
⑦. AopNamespaceHandler的init方法
AopNamespaceHandler的init方法
@Override
public void init() {
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
//aspectj-autoproxy标签,
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
⑧. 通过NamespaceHandler的parse方法解析aspectj-autoproxy标签
具体的转换工作委托给了BeanDefinitionParser实例:
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1、注册AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 2、处理子标签<aop:include/>, 指定@Aspect类,支持正则表达式,符合该表达式的切面类才会被应用
extendBeanDefinition(element, parserContext);
return null;
⑨. AnnotationAwareAspectJAutoProxyCreator注册器分析
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 1、注册AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 2、解析子标签 proxy-target-class 和 expose-proxy
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 3、注册组件并发送组件注册事件
registerComponentIfNecessary(beanDefinition, parserContext);
}
1. 注册AnnotationAwareAspectJAutoProxyCreator
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
// 如果registry已经包含了internalAutoProxyCreator,
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果已经注册的internalAutoProxyCreator不是AnnotationAwareAspectJAutoProxyCreator,则需要判断优先级并决定使用哪个
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
// 如果已经注册的internalAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator,则无需特殊处理
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// HIGHEST_PRECEDENCE --> 指定最高优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
// ROLE_INFRASTRUCTURE --> 表示Spring的内部bean
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册BeanDefinition
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
2 .解析子标签 proxy-target-class 和 expose-proxy
⑩. <aop:include/>
标签解析
<aop:include/>
标签的作用:例如有下面的配置文件,并指定了<aop:include name=“aspectJTest”></aop:include>,则aspectJTest切面类会被应用,且name支持正则表达式,如果配置文件中的切面类不符合name的表达式,则切面类不会被应用。
⑪. AspectJAutoProxyBeanDefinitionParser 源码分析
AspectJAutoProxyBeanDefinitionParser 源码分析
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
// 解析标签的时候将会执行的方法
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 注册一个类型为AnnotationAwareAspectJAutoProxyCreator的bean到Spring容器中
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 通过读取配置文件对扩展相关属性
extendBeanDefinition(element, parserContext);
return null;
}
private void extendBeanDefinition(Element element, ParserContext parserContext) {
// 获取前面注册的AnnotationAwareAspectJAutoProxyCreator对应的BeanDefinition
BeanDefinition beanDef =
parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
// 解析当前标签的子标签
if (element.hasChildNodes()) {
addIncludePatterns(element, parserContext, beanDef);
}
}
// 解析子标签中的name属性,其可以有多个,这个name属性最终会被添加到
// AnnotationAwareAspectJAutoProxyCreator的includePatterns属性中,
// Spring在判断一个类是否需要进行代理的时候会判断当前bean的名称是否与includePatterns中的
// 正则表达式相匹配,如果不匹配,则不进行代理
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element includeElement = (Element) node;
// 解析子标签中的name属性
TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
valueHolder.setSource(parserContext.extractSource(includeElement));
includePatterns.add(valueHolder);
}
}
// 将解析到的name属性设置到AnnotationAwareAspectJAutoProxyCreator
// 的includePatterns属性中
if (!includePatterns.isEmpty()) {
includePatterns.setSource(parserContext.extractSource(element));
beanDef.getPropertyValues().add("includePatterns", includePatterns);
}
}
}