@Component,@service,@autowired等注解的实现原理默认情况下bean Name的默认⽣成策略;
@component @service @Controller @Respository
⼊⼝肯定是BeanNameGenerator接⼝声明的generateBeanName(BeanDefinition,BeanDefinitionRegistry)⽅法,该⽅法做了⼀个分类判断,处理AnnotationBeanDefinition和DefaultBeanNameGenerator两种⽅式的。这⾥只看注解⽅式。
public interface BeanNameGenerator {
String generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2);
}
AnnotationBeanDefinition.java
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
// 判断是AnnotatedBeanDefinition的实现,就从annotation获得。
if (definition instanceof AnnotatedBeanDefinition) {
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
// 是⽂本就返回这个beanName,但是也有可能annotation的value是null,就后从buildDefaultBeanName获得
if (StringUtils.hasText(beanName)) {
return beanName;
}
}
return buildDefaultBeanName(definition, registry);
}
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
// 获得类或者⽅法上所有的Annotation
AnnotationMetadata amd = Metadata();
// 得到所有annotation的类名
Set<String> types = AnnotationTypes();
String beanName = null;
for (String type : types) {
// 把annotation⾥⾯的字段与value,解读出来成map,字段名是key,value为value
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
// 判断annotation是否有效,是否存在作为beanName的字段有value
if (isStereotypeWithNameValue(type, MetaAnnotationTypes(type), attributes)) {
// 从注解中获得value字段的值,
Object value = ("value");
if (value instanceof String) {
String strVal = (String) value;
if (StringUtils.hasLength(strVal)) {
if (beanName != null && !strVal.equals(beanName)) {
throw new IllegalStateException("Stereotype annotations suggest inconsistent " +"component names: '" + beanName + "' versus '" + strVal + "'");
}
beanName = strVal;
}
}
}
}
return beanName;
}
protected boolean isStereotypeWithNameValue(String annotationType,Set<String> metaAnnotationTypes, Map<String, Object> attributes) { // 判断annotation的类型是否是这三种.
// org.springframework.stereotype.Component
// javax.annotation.ManagedBean
// javax.inject.Named
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
(metaAnnotationTypes != null && ains(COMPONENT_ANNOTATION_CLASSNAME)) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
// 并且value存在值。才会返回true
return (isStereotype && attributes != null && ainsKey("value"));
}
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return buildDefaultBeanName(definition);
}
protected String buildDefaultBeanName(BeanDefinition definition) {
// 获得类名
String shortClassName = BeanClassName());
// 把类名第⼀个字母⼤写转⼩写
return Introspector.decapitalize(shortClassName);
}
}
debug测试:容器启动就开始注册bean
然后进⼊到红⾊箭头指向的地⽅
这⾥MconfiAop转为mconfiAop
以后注册进⼊容器中的beanName
默认的都是类名第⼀个字母⼩写,
不是默认策略就是value;⾥⾯的值value作为beanName
-------------------------------------------------- -------------------------------------------------- -----------包扫描注册⾖的原理分析
@service @Controller @Respository注解上⾯都标注了@Component注解它们之间是等效的
只是为了分层标注
@Component的实现原理:
我们知道它们是向IOC容器中注册beanDefiniton,⽽背景是⾃定义标签根据之前讲解的⾃定义标签解析
我们知道⾃定义标签的解析为如下⽅法DefaultBeanDefinitionDocumentReader.java
解析⾃定义标签的时候⾸先需要获得XML中名称空间BeanDefinitionParserDelegate.java
String namespaceUri = NamespaceURI(ele);//xmlns:context="/schema/context"
然后根据名称空间到对应的到对应的NameSpaceHandler来进⾏处理
NamespaceHandler handler = NamespaceHandlerResolver().resolve(namespaceUri);
默认在/ META-INF下spring.handler
我们最终到了ContextNamespaceHandler
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
。。。。。。。
}
这段代码中注册了许多解析器,我们重点关注ComponentScanBeanDefinitionParser
锁定解析()⽅法
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = Attribute(BASE_PACKAGE_ATTRIBUTE); // 获取base-package属性
basePackage = ReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 处理包路径中的特殊符号,如${}
// 分割
String[] basePackages = kenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
/* 配置Scanner */
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
/* 扫描 */
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
/
* 注册⼀些注解相关的PostProcessor,将BeanDefinition注册完成的事件通知给相关 */
ReaderContext(), beanDefinitions, element);
return null;
}
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new Registry(), useDefaultFilters, Environment(), ResourceLo }
直到 ClassPathScanningCandidateComponentProvider.java
protected void registerDefaultFilters(){
//添加默认的组件注解的过滤器
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassLoader();
}
我们看到了默认的@Component注解过滤器的添加,⽽我们常⽤的@服务,@控制器等注解都使⽤了@Component注解,所以同样会匹配
这个过滤器。
protected Set <BeanDefinitionHolder> doScan(String ... basePackages){
设置<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet <BeanDefinitionHolder>();
for(String basePackage:basePackages){
/ *获取候选的BeanDefinition * /
Set <BeanDefinition> candidates = findCandidateComponents(basePackage);
for(BeanDefinition candidate:candidate){
/ *处理@Scope注解元数据* /
ScopeMetadata scopeMetadata = solveScopeMetadata(candidate);
candidate.setScope(ScopeName());
//⽣成beanName
String beanName = ateBeanName(candidate,istry);
resource和autowired注解的区别if(候选instanceof AbstractBeanDefinition){
postProcessBeanDefinition((AbstractBeanDefinition)candidate,beanName);
}
如果(候选的instanceof AnnotatedBeanDefinition){
//其他注解的处理
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)候选);
}
//检查BeanDefinition
if(checkCandidate(beanName,candidate)){
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate,beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,definitionHolder,istry);
beanDefinitions.add(definitionHolder);
//注册BeanDefinition
registerBeanDefinition(definitionHolder,istry);
}
}
}
返回的BeanDefinitions;
findCandidateComponents()⽅法会获取basePackage的值
⾥⾯的isCandidateComponent()⽅法⽤来过滤之前添加的过滤器过滤资源
protected boolean isCandidateComponent(MetadataReader metadataReader)throws IOException {
// excludeFilter过滤
for(TypeFilter tf:ludeFilters){
if(tf.match(metadataReader,adataReaderFactory)){
return false;
}
}
//
includeFilter 过滤for(TypeFilter tf:this.includeFilters){
if(tf.match(metadataReader,adataReaderFactory)){
// @Conditional注解解析和判断
return isConditionMatch(metadataReader);
}
}
返回false;
}
默认情况excludeFilters是空的,includeFilters包含之前添加的@Component注解的AnnotationTypeFilt
er,所以这⾥会过滤掉不包含@Component注解的类。然后就是⽣成beanDifiniton和注册beanDefinition
@Autowired
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论