@PropertySource
- 通过该标签读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部配置文件以后可以使用${}取出配置文件中的值。
- 代码
- 配置类
@Configuration @PropertySource({"classpath:/person.properties","classpath:/animal.properties"}) public class BeanConfig { @Bean public Student student(){ return new Student(); } @Bean public MyPostProcess myPostProcess(){ return new MyPostProcess(); } }
- 实体类
@Getter public class Student { @Value("${person.name}") private String name; public Student(){ System.out.println("student . . . constructor"+name); } @PostConstruct public void init(){ System.out.println("student init...."+name); } }
- 测试结果,可以看出在调用构造方法的时候,没有进行设置属性,在初始化方法之前将对象创建好,并且赋值好了,然后调用初始化方法
自动装配
-
@Autowired
- 默认优先按照类型去容器中找对应的组件:applicationContext.getBean(Person.class)
- 如果找到多个相同类型的组件,再将属性(注入对象的地方)的名称,作为组件id去容器中查找。使用@Qualifier(“id名称”)来指定注入的对象是哪个ID(如果没有指定ID,则ID为类名,可以在@Bean进行ID的指定),而不是使用属性名。
BookService{ //此时会去容器中找,id为bookDao1的BookDao @Autowired BookDao bookDao1; @Autowired //虽然属性名称是bookDao3,但是指定注入对象的ID为bookDao @Qualifier("bookDao") BookDao bookDao3; }
- 自动装配,默认一定要将属性赋值好,没有就会报错。可以使用@Qualifier(required=false)来设置,当没有对象注入时,也不会报错。此时组件为null。
-
@Primary,让spring进行自动装配时,默认使用首选的bean,也可以继续使用@Qualifier指定需要装配的bean。
- @Primary用于生产Bean对象的地方,让spring看到哪个bean是优先装配的,修改默认装配的bean为@Primary修饰的bean。
- @Qualifier用于注入Bean对象的地方,如果指定了就会根据ID值来进行装配,不会走默认首选装配的bean。
-
应用
- 实体类
//设置id为mysql @Component("mysql") @Primary @ToString public class MySqlDataSourse extends BaseDataSourse { public MySqlDataSourse(){ name = "mysql"; } @Override public String toString() { return "MysqlDataSource["+name+"]"; } }
//设置id值为oracle @Component("oracle") public class OracleDataSource extends BaseDataSourse { public OracleDataSource(){ name = "oracle Datasourse"; } @Override public String toString() { return "OracleDataSource["+name+"]"; } }
- 测试类
@Getter @ToString public class Student { @Autowired @Qualifier("oracle") private BaseDataSourse baseDataSourse; public Student(){ System.out.println("student . . . constructor"); } @PostConstruct public void init(){ System.out.println("student init...."+baseDataSourse); } }
- 情况:
- 如果没有@Primary和@Qualifier注解,Student会报错,原因,是注入的是父类,存在两个子类,spring无法找到确切的信息,注入哪个。
- 在MysqlDataSourse上面添加上@Primary表明了,优先注入这个对象,所以,当只存在@Primary对象时,spring在注入时,会选择优先注入的对象。
- 当存在@Qualifier注解时,即表明了,需要注入具体id的对象,spring优先注入的对象即实效。如果通过id找不到对象,则会报错,也可以使用required=false来设置,可以注入为null。
- 存在的情况
- 不存在的情况
-
@Resource(JSR250规范)
- 可以像@Autowired实现自动装配的功能,默认是按照组件名称进行自动装配的。
- 缺点
- 没有支持@Primary的功能
- 没有支持@Autowired(required=false)的功能
-
@Inject(JSR330规范)
- 需要导入javax.inject包,和Autowired功能一样,没有required=false的功能
-
区别
- @Autowired是spring框架的
- 其他两个是Java规范的
@Autowired
- 可以在构造器,参数,方法,属性进行标记
- 【标注在方法上】:spring创建当前对象的时候,就会调用方法,完成赋值。方法使用的参数,自定义类型的值从IOC容器中进行获取。特别的,使用@Bean创建对象时,参数从容器中获取,而且默认不写@Autowired
//此处的car从容器中获取,可以在参数的位置添加注解@Autowired也可以不加,spring自动实现
@Bean
public Person person(Car car){
return new Person(car);
}
- 【标记在构造器上】:
- spring中,默认加载IOC容器中的组件,容器启动会调用无参的构造器创建对象,再进行初始化赋值等操作
- 当标在有参构造器上,spring加载时,会默认调用有参构造器,而且构造器要用的参数,会从容器中获取
- 如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件从容器中获取
@Component
class Person{
private Car car;
//1. 此处可以在方法上加@Autowired
// @Autowired
//2. 也可以在方法的参数上加
// public Person(@Autowired Car car)
//3. 但是,因为只有一个有参构造器,所以可以省略,spring会自动寻找并注入
public Person(Car car){
this.car = car;
}
}
- 【标记在参数上】:从容器中获取对象,进行赋值等操作
注意:
1. 标在构造器位置,如果组件只有一个有参构造器,如果这个有参构造器的Autowired可以省略,参数位置的组件还是可以从容器中获取
2. 使用@Bean进行创建对象时,方法参数的值也是从容器中获取,而不用特别指定,当然也可以使用@Autowired注解,进行注入。