第三方jar包的对象往往都不会自带@Service、@Component或者其他,但是我们需要让这些对象启动时就注入到Spring容器中,这就需要使用@Bean注解来实现
常用做法:
@Bean语法
@Configuration
public class CommonConfig{
@Bean
public Country country(){
return new Country();
}
@Bean
public Province province(Country country){
System.out.println(country);
return new Province();
}
}
//测试
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(SpringBootTestApplication.class, args);
Country country = context.getBean(Country.Class);
System.out.println(country);
}
如果方法的内部需要使用ioc容器中已经存在的Bean对象,只需要在方法中指定入参即可,Spring会自动注入
@Import语法
在Spring的启动类上添加@Import注解,可以指定配置类加载到Spring容器中
@Import(CommonConfig.class)//多个配置类用逗号分隔
@SpringBootApplication
public class SpringBootRegistApplication{
SpringApplication.run(SpringBootTestApplication.class, args);
}
思考:当配置类多的时候,SpringBoot既然是为了解决项目臃肿问题,是否有更好的方式来优雅的实现
方式1:实现ImportSelector接口
public class CommonImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata){
return new String[]{"com.squirtle.test.config.CommonConfig","..."};//有多少个配置类,就在String数组里面加入多少个
}
}
@Import(CommonImportSelector.class)
@SpringBootApplication
public class SpringBootRegistApplication{
SpringApplication.run(SpringBootTestApplication.class, args);
}
方式2:使用配置文件+ImportSelector方式
一行表示一个配置类
com.squirtle.test.config.CommonConfig
xxx.xxxx.xxxx.xxx.xxx
xxx.xxx.xxx.xxx.xxx
public class CommonImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata){
List<String> imports = new ArrayList<>();
InputStream is = CommonImportSelector.class.getClassLoader().getResourceAsStream("common.imports");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
try{
while((line=br.readLine()) != null){
imports.add(line);
}
}catch(IOException e){
throw new RuntimeException(e);
}finally{
if(br != null){
try{
br.close();
}catch(IOException e){
throw new RuntimeException(e);
}
}
}
return imports.toArray(new String[0])
}
}
想要更优雅,则可以自定义注解,无需在SpringBoot启动类上指定包路径了
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(CommonImportSelector.class)
public @interface EnableCommonConfig{
}
@EnableCommonConfig
@SpringBootApplication
public class SpringBootRegistApplication{
SpringApplication.run(SpringBootTestApplication.class, args);
}