目录
@Autowired
自动注入:
- 默认优先按照类型去容器中找对应的组件
annotationConfigApplicationContext.getBean(PersonDao.class)- 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
annotationConfigApplicationContext.getBean("personDao")- 使用@Qualifier指定要注入哪个组件,根据id来,而不是默认的属性名
- 自动装配默认一定要将属性赋值好,没有就会报错,可以通过
@Autowired(required = false) 来解决 @Primary:让spring容器在自动装配的时候,默认首选的bean,也可以继续使用@Qualifier来制定(即@Qualifier 的优先级最高)
实体bean:
package com.cjian.dao;
import org.springframework.stereotype.Repository;
/**
* @description:
* @author: cWX969834
* @time: 2020/10/28 11:25
*/
@Repository
public class PersonDao {
private String label;
public PersonDao() {
}
public PersonDao(String label) {
this.label = label;
}
@Override
public String toString() {
return "PersonDao{" + "label='" + label + '\'' + '}';
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
我们在这里使用@Autowired注入了一个personDao
package com.cjian.service;
import com.cjian.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @description:
* @author: cWX969834
* @time: 2020/10/28 11:25
*/
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao + '}';
}
}
配置类:
package com.cjian.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @description:
* @author: cWX969834
* @time: 2020/10/28 9:32
*/
@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {
/* @Bean("personDao2")
public PersonDao personDao() {
return new PersonDao("2");
}*/
}
测试代码:
package com.cjian;
import com.cjian.config.MainConfigAutowired;
import com.cjian.dao.PersonDao;
import com.cjian.service.PersonService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @description:
* @author: cWX969834
* @time: 2020/11/3 11:13
*/
public class TestAutowired {
static AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
MainConfigAutowired.class);
public static void main(String[] args) {
String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
System.out.println(annotationConfigApplicationContext.getBean(PersonDao.class));
System.out.println(annotationConfigApplicationContext.getBean("personDao"));
System.out.println(annotationConfigApplicationContext.getBean(PersonService.class));
}
}
输出:
PersonDao{label='null'}
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}
证明了默认是按照类型去容器中找对应的组件
测试,如果我们将配置类的注解放开:
@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {
@Bean("personDao2")
public PersonDao personDao() {
return new PersonDao("2");
}
}
再次运行时,会报错:
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.cjian.dao.PersonDao' available: expected single matching bean but found 2: personDao,personDao2
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:420)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
at com.cjian.TestAutowired.main(TestAutowired.java:26)
这时候容器里面有两个personDao的组件,但是也不应该报这个错,报这个错是由于System.out.println(annotationConfigApplicationContext.getBean(PersonDao.class)); 这行代码导致的,它不知道该获取哪个组件,注释该代码后运行如下:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}
此时验证了,如果容器中有多个组件,会按照id去查找(persongService里注入的是personDao),即相当于annotationConfigApplicationContext.getBean("personDao");
再来验证下,我们将service里注入的dao的名字改成这样的:
@Service
public class PersonService {
@Autowired
private PersonDao personDao2;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao2 + '}';
}
}
输出:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}
再次验证如果容器中有多个组件,会按照id去查找,
如果这时候,就算我们定义了
private PersonDao personDao2;但是我们任然想获取personDao咋办呢?
使用@Qualifier注解:
@Service
public class PersonService {
@Qualifier("personDao")
@Autowired
private PersonDao personDao2;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao2 + '}';
}
}
输出:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}
验证结束!
使用@Primary来设置默认装备哪个bean:
@Configuration //告诉spring这是一个配置类
@ComponentScan( {"com.cjian.dao", "com.cjian.service", "com.cjian.controller"})
public class MainConfigAutowired {
@Primary
@Bean("personDao2")
public PersonDao personDao() {
return new PersonDao("2");
}
}
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
@Autowired可以用在构造器,方法,参数,属性上
- 标注在方法上:@Bean+方法参数,参数会从容器中获取,默认不写@Autowired
- 标注在构造器上,如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还可以自动从容器中获取
- 放在参数位置
@Resource
JSR250 的java规范
可以和@Autowired一样实现自动装配的功能,默认是按照组件名称装配的,不支持@Primary和@Autowired(required=false)的功能
@Service
public class PersonService {
// @Qualifier("personDao")
// @Autowired(required = false)
@Resource
private PersonDao personDao2;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao2 + '}';
}
}
输出:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}
@Service
public class PersonService {
// @Qualifier("personDao")
// @Autowired(required = false)
@Resource(name="personDao")
private PersonDao personDao2;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao2 + '}';
}
}
输出:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='null'}}
@Inject
也是JSR250的java规范
和@Autowired功能一样,但是不支持@Autowired(required=false)的功能
需要导入依赖:
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
@Service
public class PersonService {
// @Qualifier("personDao")
// @Autowired(required = false)
//@Resource(name="personDao")
@Inject
private PersonDao personDao2;
@Override
public String toString() {
return "PersonService{" + "personDao=" + personDao2 + '}';
}
}
输出:
PersonDao{label='null'}
PersonService{personDao=PersonDao{label='2'}}