@Component,@service,@autowired等注解的实现原理 |
您所在的位置:网站首页 › @service注解原理 › @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 = annotatedDef.getMetadata(); // 得到所有annotation的类名 Set types = amd.getAnnotationTypes(); 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, amd.getMetaAnnotationTypes(type), attributes)) { // 从注解中获得value字段的值, Object value = attributes.get("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 metaAnnotationTypes, Map attributes) { // 判断annotation的类型是否是这三种. // org.springframework.stereotype.Component // javax.annotation.ManagedBean // javax.inject.Named boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) || (metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) || annotationType.equals("javax.annotation.ManagedBean") || annotationType.equals("javax.inject.Named"); // 并且value存在值。才会返回true return (isStereotype && attributes != null && attributes.containsKey("value")); } protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return buildDefaultBeanName(definition); } protected String buildDefaultBeanName(BeanDefinition definition) { // 获得类名 String shortClassName = ClassUtils.getShortName(definition.getBeanClassName()); // 把类名第一个字母大写转小写 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 = this.getNamespaceURI(ele);//xmlns:context="http://www.springframework.org/schema/context"然后根据名称空间找到对应的找到对应的NameSpaceHandler来进行处理 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);默认在/ META-INF下spring.handler 我们最终找到了ContextNamespaceHandler public class ContextNamespaceHandler extends NamespaceHandlerSupport { public void init() { this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); this.registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); this.registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); this.registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); 。。。。。。。} 这段代码中注册了许多解析器,我们重点关注ComponentScanBeanDefinitionParser 锁定解析()方法 public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); // 获取base-package属性 basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); // 处理包路径 中的特殊符号,如${} // 分割 String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); /* 配置Scanner */ ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); /* 扫描 */ Set beanDefinitions = scanner.doScan(basePackages); /* 注册一些注解相关的PostProcessor,将BeanDefinition注册完成的事件通知给相关监听器 */ registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }protected void registerDefaultFilters(){ //添加默认的组件注解的过滤器 this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); } 我们看到了默认的@Component注解过滤器的添加,而我们常用的@服务,@控制器等注解都使用了@Component注解,所以同样会匹配这个过滤器。 protected Set doScan(String ... basePackages){ Assert.notEmpty(basePackages,“必须至少指定一个基本包”); 设置 beanDefinitions = new LinkedHashSet (); for(String basePackage:basePackages){ / *获取候选的BeanDefinition * / Set candidates = findCandidateComponents(basePackage); for(BeanDefinition candidate:candidate){ / *处理@Scope注解元数据* / ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //生成beanName String beanName = this.beanNameGenerator.generateBeanName(candidate,this.registry); 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,this.registry); beanDefinitions.add(definitionHolder); //注册BeanDefinition registerBeanDefinition(definitionHolder,this.registry); } } } 返回的BeanDefinitions; findCandidateComponents()方法会获取basePackage的值
protected boolean isCandidateComponent(MetadataReader metadataReader)throws IOException { // excludeFilter过滤 for(TypeFilter tf:this.excludeFilters){ if(tf.match(metadataReader,this.metadataReaderFactory)){ return false; } } // includeFilter 过滤for(TypeFilter tf:this.includeFilters){ if(tf.match(metadataReader,this.metadataReaderFactory)){ // @Conditional注解解析和判断 return isConditionMatch(metadataReader); } } 返回false; } 默认情况excludeFilters是空的,includeFilters包含之前添加的@Component注解的AnnotationTypeFilter,所以这里会过滤掉不包含@Component注解的类。然后就是生成beanDifiniton和注册beanDefinition @Autowired我们知道在整合SSM项目中我们一般是在实现类上加上@Component等组件,但是我们使用@Autowired注解注入的时候其实注入得是类型的接口下面看看演示: 如果使用@resource需要改变注入到beanName ---按名称装配 在@Autowired的定义中有下面一段话:链接 Note that actual injection is performed through a BeanPostProcessor which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).
有图可知AutowiredAnnotationBeanPostProcessor实现了BeanPostProcessor的,IOC容器启动时候@Autowired注解会工作 @autowired注释会自动装配按类型 这种类型有多个则会按照注册的属相值作为id注入:容器中有两个UserDao类型userdao1 userdao2,@ UserDao userdao2 则注入的userdao2类型加上@Qualifier( “userdao1”):使用@Qualifier指定需要装配的组件的ID,而不是使用属性名,明确指定使用userdao1自动装配默认一定要将属性赋值好,没有就会报错;可以使用@Autowired(required = false); @Primary:让春天进行自动装配的时候,默认使用首选的豆; 下面看看原理:我们知道AutowiredAnnotationBeanPostProcessor实现的,查看该类的源码会发现它实现了MergedBeanDefinitionPostProcessor接口,进而实现了接口中的postProcessMergedBeanDefinition方法。 来源 根据对Spring源码的分析我们知道BeanPostProcessor原理在对豆的实例化和初始化时AbstractAutowireCapableBeanFactory.java中的doCreateBean方法中有这样一段代码 synchronized(mbd.postProcessingLock) { if(!mbd.postProcessed) { try { this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable var17) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17); } mbd.postProcessed = true; } }在这段代码中会执行applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName),深入这段代码又会执行postProcessMergedBeanDefinition protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) { Iterator var4 = this.getBeanPostProcessors().iterator(); while(var4.hasNext()) { BeanPostProcessor bp = (BeanPostProcessor)var4.next(); if(bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor)bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }接口 public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { void postProcessMergedBeanDefinition(RootBeanDefinition var1, Class var2, String var3); }实现类 public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { 。。。。。。 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { if(beanType != null) { //找到@autowired注解 InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null); metadata.checkConfigMembers(beanDefinition); } } 。。。。。。。 } 上述信息:找到beanName(也重要)如何找到策略有疑惑 AnnotationAttributes ann = AutowiredAnnotationBeanPostProcessor.this.findAutowiredAnnotation(bridgedMethod); //找到所有的注解方法 private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) { if(ao.getAnnotations().length > 0) { //遍历所有的@autowired注解类型 Iterator var2 = this.autowiredAnnotationTypes.iterator(); while(var2.hasNext()) { Class |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |