spring @Component原理及自定义实现

spring @Component原理及自定义实现,第1张


spring @Component原理及自定义实现

         

            

                                         

@Component 原理

        

@Component扫描注册调用栈

# ClassPathBeanDefinitionScanner类
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:280)

# ComponentScanAnnotationParser类
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128)

# ConfigurationClassParser类
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)

# ConfigurationClassPostProcessor类
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)

# PostProcessorRegistrationDelegate类
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)

# AbstractApplicationContext类
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
	  - locked <0xe7b> (a java.lang.Object)

# ServletWebServerApplicationContext类
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)

# SpringApplication类
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)

# 项目启动入口
at com.example.demo.DemoApplication.main(DemoApplication.java:16)

           

ComponentScan

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};      //指定扫描的包

    @AliasFor("value")
    String[] basePackages() default {}; //与value等效

    Class[] basePackageClasses() default {};   //指定扫描的类

    Class nameGenerator() default BeanNameGenerator.class;
                                        //指定beanName生成器

    Class scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;     //是否使用默认的过滤器
    ComponentScan.Filter[] includeFilters() default {};  //包含的过滤器
    ComponentScan.Filter[] excludeFilters() default {};  //排除的过滤器

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;  //默认注解过滤

        @AliasFor("classes")
        Class[] value() default {};    //可以设置自定义过滤器

        @AliasFor("value")
        Class[] classes() default {};

        String[] pattern() default {};
    }
}

            

FilterType

public enum FilterType {
    ANNOTATION,       //指定的注解类(可以是自定义的注解类)
    ASSIGNABLE_TYPE,  //过滤指定的类
    ASPECTJ,  //aspectJ表达式
    REGEX,    //正则表达式
    CUSTOM;   //自定义过滤器(自定义匹配规则)

    private FilterType() {
    }
}

           

TypeFilter:实现该接口,可自定义过滤匹配规则

@FunctionalInterface
public interface TypeFilter {
    boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}

                            

@ComponentScan使用示例

@ComponentScan(includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {CustomComponent.class}), 
                             //标注了@CustomComponent注解的类会被注册
        @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.example.demo.service..*"),
                             //扫描注册正则表达式匹配的类
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {CustomFilter.class}),
                             //自定义类过滤器,匹配的类会被扫描注册
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {HelloServiceImpl.class})
                             //扫描注册指定的类
})

           

ComponentScanParser:根据@ComponentScan注解扫描注册类

class ComponentScanAnnotationParser {
    private final Environment environment;
    private final ResourceLoader resourceLoader;
    private final BeanNameGenerator beanNameGenerator;
    private final BeanDefinitionRegistry registry;

    public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader, BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {
        this.environment = environment;
        this.resourceLoader = resourceLoader;
        this.beanNameGenerator = beanNameGenerator;
        this.registry = registry;
    }

    public Set parse(AnnotationAttributes componentScan, String declaringClass) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
        Class generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : (BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
                //设置beanName生成器
        ScopedProxyMode scopedProxyMode = (ScopedProxyMode)componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        } else {
            Class resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver((ScopeMetadataResolver)BeanUtils.instantiateClass(resolverClass));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));
        AnnotationAttributes[] var15 = componentScan.getAnnotationArray("includeFilters");
        int var8 = var15.length;

        int var9;
        AnnotationAttributes excludeFilterAttributes;
        List typeFilters;
        Iterator var12;
        TypeFilter typeFilter;
        for(var9 = 0; var9 < var8; ++var9) {
            excludeFilterAttributes = var15[var9];
            typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment, this.resourceLoader, this.registry);
            var12 = typeFilters.iterator();

            while(var12.hasNext()) {
                typeFilter = (TypeFilter)var12.next();
                scanner.addIncludeFilter(typeFilter);
            }   //添加include过滤器
        }

        var15 = componentScan.getAnnotationArray("excludeFilters");
        var8 = var15.length;

        for(var9 = 0; var9 < var8; ++var9) {
            excludeFilterAttributes = var15[var9];
            typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment, this.resourceLoader, this.registry);
            var12 = typeFilters.iterator();

            while(var12.hasNext()) {
                typeFilter = (TypeFilter)var12.next();
                scanner.addExcludeFilter(typeFilter);
            }   //添加exclude过滤器
        }

        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set basePackages = new LinkedHashSet();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        String[] var19 = basePackagesArray;
        int var21 = basePackagesArray.length;

        int var22;
        for(var22 = 0; var22 < var21; ++var22) {
            String pkg = var19[var22];
            String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
            Collections.addAll(basePackages, tokenized);
        }

        Class[] var20 = componentScan.getClassArray("basePackageClasses");
        var21 = var20.length;

        for(var22 = 0; var22 < var21; ++var22) {
            Class clazz = var20[var22];
            basePackages.add(ClassUtils.getPackageName(clazz));
        }

        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }                  //扫描指定的包
}

           

ClassPathBeanDefinitionScanner:扫描注册beanDefinition

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
    private final BeanDefinitionRegistry registry;
    private BeanDefinitionDefaults beanDefinitionDefaults;
    @Nullable
    private String[] autowireCandidatePatterns;
    private BeanNameGenerator beanNameGenerator;
    private ScopeMetadataResolver scopeMetadataResolver;
    private boolean includeAnnotationConfig;


    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {


    public final BeanDefinitionRegistry getRegistry() {
    public BeanDefinitionDefaults getBeanDefinitionDefaults() {

    public void setBeanDefinitionDefaults(@Nullable BeanDefinitionDefaults beanDefinitionDefaults) {
    public void setAutowireCandidatePatterns(@Nullable String... autowireCandidatePatterns) {

    public void setScopeMetadataResolver(@Nullable ScopeMetadataResolver scopeMetadataResolver) {
    public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {
    public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {
    public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {


    public int scan(String... basePackages) {   //扫描指定目录包下的类
        int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
        this.doScan(basePackages);  //执行具体扫描 *** 作
        if (this.includeAnnotationConfig) {
            AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
        }

        return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
    }

    protected Set doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set beanDefinitions = new LinkedHashSet();
        String[] var3 = basePackages;
        int var4 = basePackages.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String basePackage = var3[var5];
            Set candidates = this.findCandidateComponents(basePackage);
                                                    //查找component注解类
            Iterator var8 = candidates.iterator();

            while(var8.hasNext()) {
                BeanDefinition candidate = (BeanDefinition)var8.next();
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                                   //生成beanName,后续用来注册bean
                if (candidate instanceof AbstractBeanDefinition) {
                    this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
                }

                if (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
                }

                if (this.checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    beanDefinitions.add(definitionHolder);
                    this.registerBeanDefinition(definitionHolder, this.registry);
                }   //注册bean信息
            }
        }

        return beanDefinitions;
    }

    protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
    protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    protected boolean isCompatible(BeanDefinition newDefinition, BeanDefinition existingDefinition) {

    private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {

          

AnnotationBeanNameGenerator:注解标注的类生成beanName

public class AnnotationBeanNameGenerator implements BeanNameGenerator {
    public static final AnnotationBeanNameGenerator INSTANCE = new AnnotationBeanNameGenerator();
    private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
    private final Map> metaAnnotationTypesCache = new ConcurrentHashMap();

    public AnnotationBeanNameGenerator() {
    }

    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        if (definition instanceof AnnotatedBeanDefinition) {  //如果是注解标注的类
            String beanName = this.determineBeanNameFromAnnotation((AnnotatedBeanDefinition)definition);
                                //生成beanName
            if (StringUtils.hasText(beanName)) {
                return beanName;
            }   //如果注解中设置了value(beanname),且不为空,则直接返回
        }

        return this.buildDefaultBeanName(definition, registry); 
                   //如果没有设置,通过类名获取beanName
    }

    @Nullable
    protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
        AnnotationMetadata amd = annotatedDef.getMetadata();
        Set types = amd.getAnnotationTypes();
        String beanName = null;
        Iterator var5 = types.iterator();

        while(var5.hasNext()) {
            String type = (String)var5.next();
            AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
            if (attributes != null) {
                Set metaTypes = (Set)this.metaAnnotationTypesCache.computeIfAbsent(type, (key) -> {
                    Set result = amd.getMetaAnnotationTypes(key);
                    return result.isEmpty() ? Collections.emptySet() : result;
                });
                if (this.isStereotypeWithNameValue(type, metaTypes, attributes)) {
                    Object value = attributes.get("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 metaAnnotationTypes, @Nullable Map attributes) {
        boolean isStereotype = annotationType.equals("org.springframework.stereotype.Component") || metaAnnotationTypes.contains("org.springframework.stereotype.Component") || annotationType.equals("javax.annotation.ManagedBean") || annotationType.equals("javax.inject.Named");
        return isStereotype && attributes != null && attributes.containsKey("value");
    }

    protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        return this.buildDefaultBeanName(definition);
    }

    protected String buildDefaultBeanName(BeanDefinition definition) {
        String beanClassName = definition.getBeanClassName();
        Assert.state(beanClassName != null, "No bean class name set");
        String shortClassName = ClassUtils.getShortName(beanClassName);
        return Introspector.decapitalize(shortClassName);
    }   //截取类名获取beanName
}

        

                   

                                         

自定义注解

      

                          

         

CustomComponent

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomComponent {

    String value() default "";
}

       

HelloService

public interface HelloService {

    String hello();
}

        

HelloServiceImpl

@CustomComponent
public class HelloServiceImpl implements HelloService {

    @Override
    public String hello() {
        return "hello";
    }
}

          

HelloController

@RestController
public class HelloController {

    @Resource
    private HelloService helloService;

    @RequestMapping("/hello")
    public String hello(){
        System.out.println(helloService.hello());

        return "hello";
    }
}

        

DemoApplication

@SpringBootApplication
@ComponentScan(includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {CustomComponent.class})
})      //设置自定义注解
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

        

localhost:8080/hello:启动应用,控制台输出

2022-04-27 19:18:13.847  INFO 5271 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 787 ms
2022-04-27 19:18:14.126  INFO 5271 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-27 19:18:14.134  INFO 5271 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.412 seconds (JVM running for 1.837)
2022-04-27 19:18:16.373  INFO 5271 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-04-27 19:18:16.373  INFO 5271 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-04-27 19:18:16.374  INFO 5271 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
hello

         

              

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/786231.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存