您的位置:首页 > 编程语言 > Java开发

spring注解驱动开发(DI功能)

2019-04-28 19:59 363 查看

一.在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();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: