zoukankan      html  css  js  c++  java
  • Springboot学习笔记(三)-常用注入组件方式

    包扫描@ComponentScan+组件标注注解(@Controller@Service@Repository@Component)

    包扫描不是必须的,指定包名后以指定的包名为准,比如指定包名为a:@ComponentScan("a"),即使b包中有标注@Controller等注解的bean也不注册。

    包扫描注解除了默认的value()还有basePackages()basePackageClasses()等方法:

    basePackages(): 指定扫描的包名(前缀)

    basePackageClasses():如果指定为A.class,那么会扫描A类所在包的类。

    includeFilters():将所指定的类注入容器。
    excludeFilters():将所指定的类排除。

    @ComponentScan.Filter中的FilterType除了给定的类型,还可以自定义:type=FilterType.CUSTOM,指定的类实现TypeFilter接口即可,同时注意不适用默认拦截器useDefaultFilters = false

    比如,定义和注入配置文件映射类需要使用注解ConfigurationPropertiesEnableConfigurationProperties,那么当配置文件变多的时候,注入起来就比较麻烦了@EnableConfigurationProperties(A.class, B.class, C.class...),所以可以使用自定义过滤器来注入所有的配置文件映射类,思路很简单,只要标注注解ConfigurationProperties就将其注入:

    public class IncludePropertiesFilter implements TypeFilter {
        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
            return metadataReader.getAnnotationMetadata().hasAnnotation(EnableConfigurationProperties.class.getName());
        }
    }
    

    在主启动类上开启过滤规则:

    @SpringBootApplication
    @ComponentScan(useDefaultFilters = false, includeFilters = @ComponentScan.Filter(type = FilterType.CUSTOM, classes = IncludePropertiesFilter.class))
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

    @Bean

    可以放在方法和注解上。

    一般放在标有@Configuration类中的方法上。如:

    @Import

    只能用在类上,最简单直观,将A注入:

    虽然直观,但需要批量注入就有点麻烦,@Import提供了高级功能:

    ImportSelector

    ImportSelector是个接口,它只有一个方法:

    String[] selectImports(AnnotationMetadata importingClassMetadata);
    

    返回值是需要注入的类型全类名,入参是指和@Import并列的全部注解信息,比如有个实现类:

    public class MyImportSelector implements ImportSelector {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            if (importingClassMetadata.hasAnnotation(UsesJava8.class.getName())) {
                return new String[]{A.class.getName()};
            }
            return new String[0];
        }
    }
    

    表示只有@UsesJava8@Import同时标注时才注入A,以下情况会生效:

    @SpringBootApplication
    @Import(MyImportSelector.class)
    @UsesJava8
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

    ImportBeanDefinitionRegistrar

    ImportBeanDefinitionRegistrar也是个接口,它只有一个方法:

    	public void registerBeanDefinitions(
    			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
    

    简单实现如下:

    public class MyImportSelector implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            registry.registerBeanDefinition("IThreadPool", new RootBeanDefinition(A.class));
        }
    }
    

    调用:

    @SpringBootApplication
    @Import(MyImportSelector.class)
    @UsesJava8
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

    注册工厂Bean

    和普通Bean不一样,普通的是通过调用构造器,而工厂是实现FactoryBean泛型接口,泛型为真正类型,通过getObject方法获取实例:

    @Configuration
    public class MyConfiguration {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
            // com.y.pojo.MyConfiguration$A
            System.out.println(context.getBean("aFactoryBean").getClass().getName());
            // com.y.pojo.MyConfiguration$AFactoryBean
            System.out.println(context.getBean("&aFactoryBean").getClass().getName());
            
            A a1 = context.getBean("aFactoryBean", A.class);
            A a2 = context.getBean("aFactoryBean", A.class);
            // false
            System.out.println(Objects.equals(a1, a2));
        }
    
        @Bean
        public AFactoryBean aFactoryBean() {
            return new AFactoryBean();
        }
    
        private static class A {
        }
    
        private static class AFactoryBean implements FactoryBean<A> {
    
            @Override
            public A getObject() throws Exception {
                return new A();
            }
    
            @Override
            public Class<?> getObjectType() {
                return A.class;
            }
    
            @Override
            public boolean isSingleton() {
                return false;
            }
        }
    }
    
  • 相关阅读:
    Java基本语法(一)
    JAVA菜鸟入门HelloWorld
    python 练习题-质数
    python 字符串转运算符
    python 提取不重复的整数
    python 句子逆序
    python 数字颠倒
    python 字符个数统计
    python 练习题-计算字符个数
    python int型正整数在内存中存储为1的个数
  • 原文地址:https://www.cnblogs.com/yw0219/p/9058605.html
Copyright © 2011-2022 走看看