spring注解驱动开发(DI功能)
一.在bean中注入Spring底层的组件
如果自定义组件想要使用Spring容器底层的一些组件,那么只需要在bean对象中实现xxxAware接口,在创建对象的时候,会调用接口规定的方法注入相关组件
1.注入IOC容器(applicationContext)
如过一个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; } }
2.注入当前bean的名字
Spring创建一个bean对象,如果想把bean的id注入到bean对象中可以实现BeanNameAware接口,用法同上。
二.成员属性赋值(@Value)和加载外部配置文件(@PropertySource)
1.编写properties文件 person.properties
person.nickName=miracle
2.编写配置类MainConfig.java
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(); } }
3.编写bean对象 Person.java
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 + '\'' + '}'; } }
4.测试
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.@Autowired
功能:自动注入
(1)默认优先按照类型去容器中找对应的组件
(2)如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
(3)@Autowired可以接收参数@Autowired(required=false),那么@Autowired在容器中找不到相同类型的bean对象来注入时,不会报错
(4)当注解 @Autowired 和 @Qualifier 同时使用可通过id指定要装配的bean,用法
@Qualifier("beanID") @Autowired
@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 { }
@Autowired标注在构造方法上的示例
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 + '}'; } }
@Autowired标注在参数上的示例
同上
2.@Primary
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.miracl 4000 e"}) @Configuration public class MainConfig2 { // @Primary注解将bookDao设置成容器中首选bean, // 当其他bean要注入bookDao时,如果容器中有多个bean的类型是bookDao // 那么使用@Autowired注解注入(不能再用@Qualifier)时,优先注入@Primary注解修饰的bean @Primary @Bean public BookDao bookDao() { return new BookDao(); } }
3.@Resource
这个注解是java规范的,和前面几个注解不兼容
(1)@Resource注解加到字段上和 @Autowired 注解效果相同
(2)@Resource注解还可以指定beanID
@Resource(name="beanID")
4.@Profile
@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();
- spring注解驱动开发(AOP功能)
- spring注解驱动开发----组件注册
- Spring学习(1):控制反转(IoC)和依赖注入(DI)的详解以及注解(annotation)开发入门案例
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(一. 环境搭建)
- Spring注解驱动开发-自动装配@Profile根据环境注册bean
- Spring注解驱动开发-组件注册(一)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(二.应用配置)
- Spring注解驱动开发-属性赋值@Value&@PropertySource
- Spring注解驱动开发-Aop体验
- Spring注解驱动开发-AOP原理简述
- Spring基于xml配置与注解驱动开发(一)
- Spring注解驱动开发-@Scope设置组件作用域
- Spring注解驱动开发-AOP原理详解
- 【视频分享】尚硅谷Java视频教程_Spring注解驱动开发视频教程
- Spring注解驱动开发-AOP(四)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(四.页面及小结)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(三.应用代码)
- Spring注解驱动开发-自动装备配@Autowired&@Qualifier
- Spring注解驱动开发-生命周期(二)
- Spring基于xml配置与注解驱动开发(二)