四类常用注解
注解 | 说明 | 位置 |
---|---|---|
@Component | 声明bean的基础注解 | 不属于以下三类时,用此注解 |
@Controller | @Component的衍生注解 | 标注在控制器类上 |
@Service | @Component的衍生注解 | 标注在业务类上 |
@Repository | @Component的衍生注解 | 标注在数据访问类上(由于与mybatis整合,用的少) |
第三方注解
如果要注册的bean对象来自第三方(不是自定义的) 不能使用@Component注解及其衍生注解声明bean需要使用如下注解进行注册
@Bean
原始方式
@SpringBootApplication
public class BootVueApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(BootVueApplication.class, args);
Country country = context.getBean(Country.class);
System.out.println(country);
}
//注入country对象
@Bean
public Country country() {
return new Country();
}
}
上述原始方式仅用于了解 在实际开发中考虑到代码的优雅美观性 、
通常将需要注册的第三方对象 放在配置类中统一进行注册
配置类统一管理
@Configuration
public class CommonConfig {
//注入country对象
@Bean
public Country country() {
return new Country();
}
//该注解生成的对象名默认为方法名
@Bean
//@Bean("aa") 可以按照实际需要自定义生成的对象名
//如果方法的内部需要使用到IOC容器中已经存在的bean对象 只需要在方法中声明即可
public Province province(Country country) {
System.out.println("province"+country);
return new Province();
}
}
@SpringBootApplication
public class BootVueApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(BootVueApplication.class, args);
//by type
Country country = context.getBean(Country.class);
System.out.println(country);
//by name
System.out.println(context.getBean("province"));
}
@Import
导入第三方对象除了上述方式 也可以通过import注解进行导入 这种情况针对于配置类不在启动类所在的包及其子包非常适用
导入配置类
@SpringBootApplication
@Import(CommonConfig.class)
public class BootVueApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(BootVueApplication.class, args);
//by type
Country country = context.getBean(Country.class);
System.out.println(country);
//by name
System.out.println(context.getBean("province"));
}
}
导入多个配置类
在实际开发中可能配置类不只一个、可以采取数组方式
@Import({CommonConfig.class,CommonConfig.class,CommonConfig.class,CommonConfig.class,CommonConfig.class,})
但是这样带来的结果是代码并不美观此时就可以使用第二种方式
导入 ImportSelector 接口实现类
这种方式只需要书写配置类的全路径名就可以
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.config.CommonConfig"};
}
}
@SpringBootApplication
//@Import({CommonConfig.class,CommonConfig.class})
@Import(CommonImportSelector.class)
public class BootVueApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(BootVueApplication.class, args);
//by type
Country country = context.getBean(Country.class);
System.out.println(country);
//by name
System.out.println(context.getBean("province"));
}
}
导入配置类文件信息
一般在实际开发中这种配置类都是以文件形式存在的 因此我们演示一下通过配置文件导入配置类的方式
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// return new String[]{"com.config.CommonConfig"};
//开始读取配置文件内容
List<String> list = new ArrayList<>();
//获取输入流
InputStream inputStream = CommonImportSelector.class.getClassLoader().getResourceAsStream("common.imports");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
try {
while ((line = reader.readLine()) != null) {
list.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return list.toArray(new String[10]);
}
}
(IOException e) {
throw new RuntimeException(e);
}
}
}
return list.toArray(new String[10]);
}
}
bean注册条件
在上述案例中、存在一个问题 注册好的对象并没有具体的值、这样做是没有意义的、接下来我们给要注册的对象赋值。
在配置文件中进行信息配置
country:
name: china
sys: local
通过SpringBoot提供的@Value
属性获取具体值
@Bean
public Country country(@Value("${country.name}") String name,@Value("${country.sys}") String sys) {
Country country = new Country();
country.setName(name);
country.setSys(sys);
return country;
}
在这里我们可以看到具体的属性值就获取到了
但如果我们在配置文件中删除了该对象的具体配置信息呢、此时就会出现错误、因为配置文件中的信息不存在
按照正常的需求、应该是在配置文件中存在的进行注入、不存在的不进行注入。基于上述需求我们就得使用SpringBoot提供的注解@Conditional
进行条件注册
bean注册条件
以下是@Conditional
注解的三个衍生注解
@ConditionalOnProperty
如果配置文件中配置了该信息则注入没有配置则不注入
@ConditionalOnProperty(prefix = "country",name={"name","sys"})
@Bean
public Country country(@Value("${country.name}") String name,@Value("${country.sys}") String sys) {
Country country = new Country();
country.setName(name);
country.setSys(sys);
return country;
}
@ConditionalOnMissingBean
如果IOC容器中不存在Country则注入Province否则不注入
@ConditionalOnMissingBean(Country.class)
@Bean
public Province province() {
return new Province();
}
@ConditionalOnClass
只有导入SpringBoot web起步依赖时才注入
//如果当前环境中存在DispatcherServlet
@ConditionalOnClass
@Bean("province1")
public Province getProvince() {
return new Province();
}