c.Controller注解:
[java- @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME)
- @Documented @Component
- public @interface Controller { String value() default ;
- }
d.Repository注解:
[java]- @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME)
- @Documented @Component
- public @interface Repository { String value() default ;
- }
通过分析Spring这4个常用的注解源码,我们看到:@Service、@Controller和@Repository注解都添加了一个@Component注解,因此他们都属于@Component
注解。
(2).ClassPathBeanDefinitionScanner扫描给定的包及其子包:
AnnotationConfigApplicationContext通过调用类路径Bean定义扫描器ClassPathBeanDefinitionScanner扫描给定包及其子包下的所有类,主要源码如下:
[java]- public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider { //创建一个类路径Bean定义扫描器
- public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { this(registry, true);
- } //为容器创建一个类路径Bean定义扫描器,并指定是否使用默认的扫描过滤规则。
- //即Spring默认扫描配置:@Component、@Repository、@Service、@Controller //注解的Bean,同时也支持JavaEE6的@ManagedBean和JSR-330的@Named注解
- public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) { //调用父类ClassPathScanningCandidateComponentProvider构造方法设置过滤规则
- super(useDefaultFilters); Assert.notNull(registry, BeanDefinitionRegistry must not be null);
- //为容器设置加载Bean定义的注册器 this.registry = registry;
- //如果注册器是资源加载器,则为容器设置资源加载器 if (this.registry instanceof ResourceLoader) {
- setResourceLoader((ResourceLoader) this.registry); }
- } //调用类路径Bean定义扫描器入口方法
- public int scan(String... basePackages) { //获取容器中已经注册的Bean个数
- int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); //启动扫描器扫描给定包
- doScan(basePackages); //注册注解配置(Annotation config)处理器
- if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
- } //返回注册的Bean个数
- return this.registry.getBeanDefinitionCount() - beanCountAtScanStart; }
- //类路径Bean定义扫描器扫描给定包及其子包 protected Set
doScan(String... basePackages) { - //创建一个集合,存放扫描到Bean定义的封装类 Set
beanDefinitions = new LinkedHashSet (); - //遍历扫描所有给定的包 for (String basePackage : basePackages) {
- //调用父类ClassPathScanningCandidateComponentProvider的方法 //扫描给定类路径,获取符合条件的Bean定义
- Set
candidates = findCandidateComponents(basePackage); //遍历扫描到的Bean - for (BeanDefinition candidate : candidates) { //获取Bean定义类中@Scope注解的值,即获取Bean的作用域
- ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //为Bean设置注解配置的作用域
- candidate.setScope(scopeMetadata.getScopeName()); //为Bean生成名称
- String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); //如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
- //设置Bean的自动依赖注入装配属性等 if (candidate instanceof AbstractBeanDefinition) {
- postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); }
- //如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解 if (candidate instanceof AnnotatedBeanDefinition) {
- //处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); }
- //根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突 if (checkCandidate(beanName, candidate)) {
- BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //根据注解中配置的作用域,为Bean应用相应的代理模式
- def