@Autowired 可以对成员变量、方法以及构造函数进行注释
相当于在配置文件中配置bean,并且使用setter注入。
就相当于是使用构造函数进行依赖注入
如果方法中有实体参数,会对方法里面的参数进行装配,并调用一次该方法
@Component
public class User {
}
@Component
public class MyTest {
@Autowired
public void myAutowired1(){
System.out.println("运行了myAutoWired1");
}
@Autowired
public void myAutowired2(User user){
System.out.println("运行了myAutoWired2,user="+user);
}
}
运行了myAutowired1
运行了myAutoWired2,user=com.chieng.boot.demo.User@4ce1d99f
Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法
类加载顺序规定先加载构造方法,再加载普通方法,当构造器中使用到属性时,会发现属性还没有被实例化,则会报错,因此,当构造方法中用到了属性时,应该将注解加在构造器上;
这段代码会报NPE,
@Autowired
private User user;
private String school;
//因为会先执行构造函数,再执行上面的依赖注入,故NPE
public UserAccountServiceImpl(){
this.school = user.getSchool();
}
当构造方法中用到了属性时,应该将注解加在构造器上,如下
private User user;
private String school;
@Autowired
public UserAccountServiceImpl(User user){
this.user = user;
this.school = user.getSchool();
}
https://www.jianshu.com/p/e44f8c6aaa27
https://blog.csdn.net/balsamspear/article/details/87936936
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies
https://mp.weixin.qq.com/s/34-DdoNcpMUlZiin6Js0Xg
spring官方依赖注入注入有2种:基于构造函数的依赖注入、基于Setter的依赖注入;
通过反射调用无参构造方法进行bean的实例化,然后调用对象的setter方法完成赋值;
将注解 放在 函数(不一定是setter函数)上;
public class UserServiceImpl implents UserService{
private UserDao userDao;
@Autowire
public setUserDao(UserDao userDao){
this.userDao = userDao;
}
}
基于字段的依赖注入
也算是基于settter注入,也是调用setter方法注入 ;
使用最广,但是并不被spring官方推荐;
public class UserServiceImpl implents UserService{
@Autowire
private UserDao userDao;
}
指的是有参构造器,将注解放在有参构造器上 即可;
public class UserServiceImpl implents UserService{
private UserDao userDao;
@Autowire
public UserServiceImpl(UserDao userDao){
this.userDao = userDao;
}
}
@Autowired只有一个属性required,默认值为true,为true时,找不到就抛异常,为false时,找不到就赋值为null
@Autowired按类型查找,如果该类型的bean不唯一,则将字段名作为beanid注入,如果还是匹配不到,则抛出异常;
可通过组合注解解决@Autowired()@Qualifier("baseDao")
例子
两个同类型的bean不能注入
public class ServiceA {
@Autowired
private ServiceB serviceB;
public String test(){
return serviceB.tb();
}
}
public class ServiceBImplOne implements ServiceB{
@Override
public String tb() {
return "ServiceBImplOne";
}
}
public class ServiceBImplTwo implements ServiceB{
@Override
public String tb() {
return "ServiceBImplTwo";
}
}
<bean id="sa" class="example.autowired.auto.ServiceA"/>
<bean id="s1" class="example.autowired.auto.ServiceBImplOne"/>
<bean id="s2" class="example.autowired.auto.ServiceBImplTwo"/>
但是注意下面这个,是可以成功注入的;
public class ServiceA {
//先根据类型注入,但是此时有2个类型相同的,故根据filename注入,ServiceB s1,s1=ServiceBImplOne的beanid,故注入成功
@Autowired
private ServiceB s1;
public String test(){
return s1.tb();
}
}
public class ServiceBImplOne implements ServiceB{
@Override
public String tb() {
return "ServiceBImplOne";
}
}
public class ServiceBImplTwo implements ServiceB{
@Override
public String tb() {
return "ServiceBImplTwo";
}
}
<bean id="sa" class="example.autowired.auto.ServiceA"/>
<bean id="s1" class="example.autowired.auto.ServiceBImplOne"/>
<bean id="s2" class="example.autowired.auto.ServiceBImplTwo"/>
@Resource有两个常用属性name、type,所以分4种情况
同时指定name和type:则从Spring上下文中找到唯一匹配的bean进行装配
指定name:通过name找到唯一的bean,找不到抛出异常
指定type:通过tpye找到唯一的bean,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
都不指定:通过字段名作为key去查找,找到则赋值;找不到则再通过字段类型去查找,如果不唯一,则抛出异常:NoUniqueBeanDefinitionException
https://blog.csdn.net/riemann_/article/details/97698560
spring bean默认单例,是线程不安全的,但是如果不涉及到修改数据则是安全的;
例如以下代码,单例情况下,线程不安全,因为涉及到对成员num的修改;
@Controller
public class ScopeTestController {
private int num = 0;
@RequestMapping("/testScope")
public void testScope() {
System.out.println(++num);
}
@RequestMapping("/testScope2")
public void testScope2() {
System.out.println(++num);
}
}
但是,像是一般的service层却可以使用单例;
service层
@Service
public xx class {
@Resource
xxxMapper xxxMapper;
public List(Xxx) getAll( ... ){
...
}
}
Controller层
@Controller
public xx class {
@Resource
xxxService xxxService;
Object ...{
List data = xxxService.getAll(...)
}
}
以上不涉及到数据修改,xxxMapper、xxxService虽然是成员变量,但是本身只是提供方法,最终的数据是List data = xxxService.getAll(…)并不是成员变量,故是线程安全的;