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;
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM