本文将会讲到SpringBoot的IOC模块下的注解进行总结,主要目的是为了方便之后查找注解和快速应用。
将会以:组件注册,生命周期,属性赋值,自动装配来进行区分。示例代码的注解很重要
三、属性赋值
1、@Value:标注在变量上。在 bean 里的对象可以用 @Value 来初始值。
2、@PropertySource:标注在类上。加载外部配置文件,外部配置文件里的属性会被放入环境变量中。
详细例子:https://blog.youkuaiyun.com/qq_41075649/article/details/83419588
四、自动装配
1、@Autowired:可标注在属性、方法名、构造器、新参上。自动注入,所调用的参数都是从 ioc 容器中获取,自动装配进容器中。
@Configuration
@ComponentScan({"com.duojia.controller", "com.duojia.service"})
public class MainConfigOfAutowired {
}
@Controller
public class BookController {
@Autowired
private BookService bookService;
}
@Service
public class BookService {
@Autowired(required=false) // required=false 表示该bean可以为null
private BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
}
2、@Qualifier:标注在属性上。在容器中有多个相同类型的组件时,用@Autowired自动装配会按名称来注册,而用@Qualifier可以指定名称。
@Service
public class BookService {
@Qualifier("bookDao")
private BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
}
3、@Primary:标注属性上。在容器中有多个相同类型的组件时,拥有@Primary注解的Bean会先被注册进去。(与@Qualifier不能同时存在)
@Configuration
@ComponentScan({"com.duojia.controller", "com.duojia.dao", "com.duojia.service", "com.duojia.bean"})
public class MainConfigOfAutowired {
@Primary
@Bean("bookDao2")
public BookDao bookDao() {
return new BookDao();
}
}
4、@Resource:标在属性上。与@Autowired功能类似,功能稍少。
@Service
public class BookService {
@Resource(name="bookDao") //与 @Autowired 类似
private BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
}
5、@Inject:标在属性上。与@Autowired功能类似,需要引入外部依赖
@Service
public class BookService {
@Inject
private BookDao bookDao;
public BookDao getBookDao() {
return bookDao;
}
}
6、(非注解)自定义组件:只需实现 ***Aware 接口即可,在Spring底层有许多 ****Aware 接口,例如 ApplicationContextAware、BeanNameAware、EmbeddedValueResolverAware等。
@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
//指定 ApplicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
System.out.println("传入的ioc:" + applicationContext);
}
//指定当前 Bean 的名字
@Override
public void setBeanName(String name) {
// TODO Auto-generated method stub
System.out.println("当前Bean的名字" + name);
}
//可以解析一些字符串
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
String resolveStringValue = resolver.resolveStringValue("你好 ${os.name},我是#{20+18}");
System.out.println("解析的字符串是:" + resolveStringValue);
}
}
7、@Profile:标注在方法或类上。根据当前环境,动态地激活和切换一系列组件。
如果未加 @Profile 注解的 Bean,都会被注册到容器中。
@Profile("default") 表示默认,也会被加入到容器中。
示例:下面示例是根据环境,来决定加载哪一个数据库
//@Profile("test")
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile {
@Value("${db.user}")
private String user;
@Value("${db.driverClass}")
private String driverClass;
//链接 测试数据库
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("db.password")String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass(driverClass);
return dataSource;
}
//链接 开发数据库
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("db.password")String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test2");
dataSource.setDriverClass(driverClass);
return dataSource;
}
//链接 生产数据库
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("db.password")String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test3");
dataSource.setDriverClass(driverClass);
return dataSource;
}
}
如何动态的切换:
1)、使用命令动态参数,在 arguments 里填入 -Dspring.profiles.active= *******
2)、使用代码的方式
public class IOCTest_Profile {
//利用代码的方式实现 profile 的动态注入
@Test
public void test02() {
// 1. 创建一个 applicationContext,且为无参构造器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 2. 设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("test", "dev");
// 3. 注册主配置类
applicationContext.register(MainConfigOfProfile.class);
// 4. 启动刷新容器
applicationContext.refresh();
String[] nameForType = applicationContext.getBeanNamesForType(DataSource.class);
for(String name : nameForType) {
System.out.println(name);
}
applicationContext.close();
}
}