如过一个bean对象,想要在其内部使用applicationContext(注入applicationContext),那么此bean对象可以通过实现ApplicationContextAware接口,实例。
编写bean对象
package com.miracle.springAnnotation.bean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
// 想要在bean中获取(注入)IOC容器,那么可以实现ApplicationContextAware接口
@Component
public class Person implements ApplicationContextAware {
// 创建字段保存IOC容器
private ApplicationContext applicationContext;
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 复写接口方法
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 方法中会自动传入IOC容器,只需赋值给字段即可
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
}
Spring创建一个bean对象,如果想把bean的id注入到bean对象中可以实现BeanNameAware接口,用法同上。
person.nickName=miracle
package com.miracle.springAnnotation.config;
import com.miracle.springAnnotation.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
// 在配置类上添加 @PropertySource 注解 来加载properties文件,将k/v保存到环境变量中
// @PropertySource 注解 接收一个String数组,可以同时加载多个properties文件
// 参数形式:classpath:/com/myco/app.properties 或者 file:/path/to/file
@PropertySource(value = {"classpath:/person.properties"})
@Configuration
public class MainConfig {
@Bean
public Person person() {
return new Person();
}
}
package com.miracle.springAnnotation.bean;
import org.springframework.beans.factory.annotation.Value;
public class Person{
// 使用@Value赋值,@Value注解里面可以接收的参数:
// 1.基本数值
// 2.可以写SPEL表达式: #{}的形式
// 3.可以写${}:取出配置文件中(properties文件)的值(在运行环境变量里面的值)
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
public Person() {
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", nickName='" + nickName + '\'' +
'}';
}
}
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
// 配置类加载properties文件后,可以在IOC容器中取出properties中的值
String value = applicationContext.getEnvironment().getProperty("person.nickName");
System.out.println(value);
output:
Person{name='张三', age=18, nickName='miracle'}
miracle
功能:自动注入
(1)默认优先按照类型去容器中找对应的组件
(2)如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
(3)@Autowired可以接收参数@Autowired(required=false),那么@Autowired在容器中找不到相同类型的bean对象来注入时,不会报错
(4)当注解 @Autowired 和 @Qualifier 同时使用可通过id指定要装配的bean,用法
@Qualifier("beanID")
@Autowired
@Autowired 不仅仅可以标注在成员属性上,还可以标注在构造器,方法,参数上
创建bean对象 Boss.java
Boss需要Car对象
package com.miracle.springAnnotation.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Boss {
private Car car;
public Car getCar() {
return car;
}
// 标注在方法上,Spring容器创建当前对象,就会调用方法,完成赋值
// 方法使用的参数,自定义类型的值从ioc容器中获取(这里的参数是 Car car,Spring就会从容器中找Car类型赋值)
@Autowired
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}
}
创建bean对象 Car.java
package com.miracle.springAnnotation.bean;
import org.springframework.stereotype.Component;
@Component
public class Car {
}
package com.miracle.springAnnotation.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
// @Component注解在向ioc容器中添加组件的时候,
// Spring容器默认会调用无参构造器创建对象,再进行初始化赋值等操作
@Component
public class Boss {
private Car car;
// 构造器的Car car 参数会从容器中获取
@Autowired
public Boss(Car car) {
System.out.println("Boss有参构造器");
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}
}
同上
package com.miracle.springAnnotation.config;
import com.miracle.springAnnotation.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@ComponentScan(value = {"com.miracle"})
@Configuration
public class MainConfig2 {
// @Primary注解将bookDao设置成容器中首选bean,
// 当其他bean要注入bookDao时,如果容器中有多个bean的类型是bookDao
// 那么使用@Autowired注解注入(不能再用@Qualifier)时,优先注入@Primary注解修饰的bean
@Primary
@Bean
public BookDao bookDao() {
return new BookDao();
}
}
这个注解是java规范的,和前面几个注解不兼容
(1)@Resource注解加到字段上和 @Autowired 注解效果相同
(2)@Resource注解还可以指定beanID
@Resource(name="beanID")
@Profile 注解 是 Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能
例如:开发时,有开发环境,测试环境,生产环境
以数据源为例:有开发库,测试库,生产库,想实现动态切换
下面已配置项目数据源为例:
(1)数据库配置文件:dbconfig.properties
db.user=root
db.password=123456
db.driverClass=com.mysql.jdbc.Driver
(2)配置类:MainConfig4.java
package com.miracle.springAnnotation.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定(不加@Profile注解),任何环境下都能注册这个组件
* 加了环境标识(@Profile)的bean,只有这个环境被激活的时候才能注册到容器中
* 另外标注了@Profile("default)的bean会被激活
* 此外@Profile 还可以写在配置类上,只有是指定的环境的时候,整个配置类里面的所有所有配置才能生效
*/
// 加载数据库配置文件
@PropertySource(value = {"classpath:/dbconfig.properties"})
@Configuration
public class MainConfig4 {
// 获取数据库配置文件中参数的第一种方式
@Value("${db.user}")
private String user;
@Value("${db.driverClass}")
private String driverClass;
@Profile("test")
// 向容器中添加数据源(测试数据源)
@Bean("testDataSource") // 获取数据库配置文件中参数的第二种方式
public DataSource dataSourceTest(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置数据源信息
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jing_dong");
dataSource.setUser(user);
dataSource.setPassword(password);
return dataSource;
}
@Profile("dev")
// 向容器中添加数据源(开发数据源)
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置数据源信息
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test2");
dataSource.setUser(user);
dataSource.setPassword(password);
return dataSource;
}
@Profile("prod")
// 向容器中添加数据源(生产数据源)
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}") String password)throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置数据源信息
dataSource.setDriverClass(driverClass);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test1");
dataSource.setUser(user);
dataSource.setPassword(password);
return dataSource;
}
}
(3)激活指定环境:
方式一:
指定虚拟机参数的方式
启动java程序时,追加参数
-Dspring.profiles.active=test,dev
方式二:
创建IOC容器的时候指定哪个环境
// 创建无参的AnnotationConfigApplicationContext 对象
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 设置需要激活的环境 可以同时设置多个环境,这里设置 test和dev
applicationContext.getEnvironment().setActiveProfiles("test", "dev");
// 注册主配置类
applicationContext.register(MainConfig4.class);
// 启动刷新容器
applicationContext.refresh();