entity包下新建一个实体了News,
public class News {
private Integer id;
private String content;
public News() {
System.out.println("无参构造方法被调用");
}
public News(Integer id, String content) {
System.out.println("有参构造方法被调用");
this.id = id;
this.content = content;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "News{" +
"id=" + id +
", content='" + content + ''' +
'}';
}
}
新建一个配置类BeanValueConfig
@Configuration
public class BeanValueConfig {
@Bean
public News news(){
return new News();
}
}
新建一个测试类BeanValueConfigTest
public class BeanValueConfigTest {
@Test
public void getBeanValued(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanValueConfig.class);
System.out.println("IoC容器初始化完成");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
News news = (News) context.getBean("news");
System.out.println(news);
}
}
执行该测试,控制台打印如下,News的属性都为空
使用@Value进行赋值,可以赋值基本数据类型或者Spring的EL表达式
修改News实体类属性部分代码如下,增加@Value注解,并添加值
@Value("1")
private Integer id;
@Value("某头部主播发布道歉信")
private String content;
执行BeanValueConfigTest测试,方法控制台打印如下
News对象创建完成之后两个属性都已经被赋值,但是这种情况数据和代码之间的耦合度比较高,因此可以将数据放在配置文件当中,实现数据和代码的解耦。在resources目录下新建config.properties配置文件
news.id=1
news.content=某头部主播各大平台账号被封
修改News实体类属性定义部分的代码
@Value("${news.id}")
private Integer id;
@Value("${news.content}")
private String content;
修改BeanValueConfig,加载配置文件,设置编码
@Configuration
@PropertySource(value = "classpath:config.properties", encoding = "utf-8")
public class BeanValueConfig {
@Bean
public News news(){
return new News();
}
}
执行测试,控制台输出如下,中文可以正常输出
如果不设置编码格式,中文会出现乱码
配置文件被加载后是放在环境变量中即org.springframework.core.env.Environment类中,可以通过容器获取environemnt对象,通过getProperty获取配置文件中配置项的值 修改测试方法,增加获取environment对象的代码
// 获取环境变量
Environment environment = context.getEnvironment();
System.out.println(environment);
System.out.println("new.content配置项的值为:" + environment.getProperty("news.content"));
执行测试,查看控制台打印的代码
项目中新建三个包dao,service,controller,分别增加三个类
@Repository
public class PersonDao {
}
@Service
public class PersonService {
// 自动装配的Bean personDao
@Autowired
private PersonDao personDao;
public PersonDao getBeanByAutowire(){
return personDao;
}
}
@Controller
public class PersonController {
@Autowired
private PersonService personService;
}
新增配置类BeanAutoAssembleConfig,将新建的三个包中的Bean注册到容器中
@ComponentScan(basePackages = {"com.citi.dao","com.citi.service","com.citi.controller"})
public class BeanAutoAssembleConfig {
}
新建测试类BeanAutoAssembleConfigTest,增加方法isSameBean()判断PersonService中使用@Autowire装配的PersonDao和从容器中获取的PersonDao对象是否为同一个对象,
public class BeanAutoAssembleConfitTest {
@Test
public void isSameBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
System.out.println("IoC容器初始化完成");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
PersonDao personDaoFromCon = (PersonDao) context.getBean("personDao");
PersonService personService = (PersonService) context.getBean("personService");
PersonDao personDaoFromAuto = personService.getBeanByAutowire();
if (personDaoFromCon == personDaoFromAuto){
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean是同一个Bean");
} else {
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean 不是 同一个Bean");
}
}
}
控制台打印如下,说明@Autowire装配的Bean和容器中的Bean是同一个Bean
在BeanAutoAssembleConfig中使用@Bean标签再注入一个PersonDao
@ComponentScan(basePackages = {"com.citi.dao","com.citi.service","com.citi.controller"})
public class BeanAutoAssembleConfig {
@Bean("personDao2")
public PersonDao personDao(){
return new PersonDao();
}
}
在测试方法中,用从容器中获取bean 的name为personDao2的Bean,与PersonService的@Autowire的Bean进行比较
public class BeanAutoAssembleConfitTest {
@Test
public void isSameBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
System.out.println("IoC容器初始化完成");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
PersonDao personDaoFromCon = (PersonDao) context.getBean("personDao2");
PersonService personService = (PersonService) context.getBean("personService");
PersonDao personDaoFromAuto = personService.getBeanByAutowire();
System.out.println(personDaoFromCon);
System.out.println(personDaoFromAuto);
if (personDaoFromCon == personDaoFromAuto){
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean是同一个Bean");
} else {
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean 不是 同一个Bean");
}
}
}
执行测试方法,控制台打印出不是同一个Bean,即persongDao2与personDao不是同一个Bean
@Autowire默认装配的Bean的类型装配的,如果需要指定的Bean进行自动装配则要使用@Qualifier("personDao2")指定Bean的name,修改PersonService类
@Service
public class PersonService {
// 自动装配的Bean personDao
@Qualifier("personDao2")
@Autowired
private PersonDao personDao;
public PersonDao getBeanByAutowire(){
return personDao;
}
}
再次执行测试类,控制台打印出是同一个Bean
@Resource与@Autowire可以起到相同的作用,不同的是@Resource默认是按照Bean的name导入的 修改PersonService,使用@Resource注入,这里PersonDao的bean name为personDao2
@Service
public class PersonService {
// 自动装配的Bean personDao
//@Qualifier("personDao")
//@Autowired
@Resource
private PersonDao personDao2;
public PersonDao getBeanByAutowire(){
return personDao2;
}
}
执行测试类,控制台打印如下
因为测试方法中从容器中获取的是bean name为personDao2的Bean,与PersonService装配的Bean为同一个Bean,可以确定@Resource是按照Bean的name来装配的,@Resource不支持@Primary, 当容器中不存在Bean时,使用@Autowire注解可以声明request=false,这时不会报错,而@Resource不支持request=false
@Resource装配顺序:
@Primary注解是作用在配置类上的,在注入Bean的方法上增加@Primary注解,当@Qualifier()与@Primary同时存在时,@Qulifier注解的功能不受影响 修改配置类如下,优先注入personDao2这个Bean
@ComponentScan(basePackages = {"com.citi.dao","com.citi.service","com.citi.controller"})
public class BeanAutoAssembleConfig {
@Primary
@Bean("personDao2")
public PersonDao personDao(){
return new PersonDao();
}
}
PersonService类代码修改如下,指定装配的Bean name为personDao
@Service
public class PersonService {
// 自动装配的Bean personDao
@Qualifier("personDao")
@Autowired
//@Resource
private PersonDao personDao2;
public PersonDao getBeanByAutowire(){
return personDao2;
}
}
测试类代码如下,增加从容器中根据类型获取Bean的方法
public class BeanAutoAssembleConfitTest {
@Test
public void isSameBean(){
ApplicationContext context = new AnnotationConfigApplicationContext(BeanAutoAssembleConfig.class);
System.out.println("IoC容器初始化完成");
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
PersonDao personDaoFromCon = (PersonDao) context.getBean("personDao2");
PersonService personService = (PersonService) context.getBean("personService");
PersonDao personDaoFromAuto = personService.getBeanByAutowire();
System.out.println(personDaoFromCon);
System.out.println(personDaoFromAuto);
if (personDaoFromCon == personDaoFromAuto){
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean是同一个Bean");
} else {
System.out.println("@Autowire自动装配的Bean和从容器中获取的Bean 不是 同一个Bean");
}
PersonDao bean = context.getBean(PersonDao.class);
System.out.println(bean.getClass().getName());
}
}
控制台正常打印,连个注解没有冲突@Qualifier执行装配的Bean的name
如果此时将@Primary注释,再次执行测试类,控制台报错
No qualifying bean of type 'com.citi.dao.PersonDao' available: expected single matching bean but found 2: personDao,personDao2,没有@Primary注解,根据类型获取Bean的时候就会报错,因为有两个Bean,容器并不知道你要的是哪一个
使用@Inject注解要导入相应的maven依赖
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
将PersonService中的@Autowire注解注释,使用@Inject注解,注释掉测试方法中注释掉根据类型获取PersonDao对象的代码,然后执行测试,同样可以装配Bean
@Resource和@Inject都是JSR250规范,@Autowire是属于Spring的注解。