阅读完需:约 4 分钟
@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。
我们对一个bean配置起属性时,是这用用的:
<property name="属性名" value=" 属性值"/>
通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注释
实例:
先写一个接口,定义了一个方法
package com.proc.bean.repository;
public interface UserRepository {
void save();
}
再写接口的实现类
@Repository("userRepository")
public class UserRepositoryImps implements UserRepository{
@Override
public void save() {
System.out.println("UserRepositoryImps save");
}
}
实现save方法,在这里指定了该bean在IoC中标识符名称为userRepository,可以不去指定,不指定就是默认的方法名开头小写。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void save(){
userRepository.save();
}
}
这里需要一个UserRepository类型的属性,通过@Autowired自动装配方式,从IoC容器中去查找到,并返回给该属性
applicationContext.xml配置
<context:component-scan base-package="com.proc.bean" />
输出:
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
serService userService=(UserService) ctx.getBean("userService");
userService.save();
结果: UserRepositoryImps save
@Autowired的原理
其实在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
注意事项:
在使用@Autowired时,首先在容器中查询对应类型的bean
- 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
- 如果查询的结果不止一个,那么@Autowired会根据名称来查找。
- 如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false
如果对应类型的bean重复了可以提供了一个@Qualifier标记,来指定需要装配bean的名称
@Autowired
@Qualifier("userJdbcImps")
private UserRepository userRepository;
特别注意:
这是我犯过的错哈!,之前一直在纠结@Autowired
注解,数据库的实现类在用,然后bean也在用,但是有时候实现类用这个注解,bean却用new来实例化,这样我就很郁闷了,既然可以new实例化,那要这个注解干啥,只是为了方便吗?有啥区别啊,那我实现类是不是也可以用new来实例化了,所以我就试了一下数据库的实现类用new来代替注解。
@SpringBootTest
class JdbcApplicationTests {
// @Autowired
// UserService userService;
@Test
void contextLoads() {
User user=new User();
UserService userService=new UserService();
user.setId(14);
user.setUsername("1sdfsasd");
user.setAddress("asd");
userService.addUser(user);
}
}
结果却是报错了:


仔细看了看报错,有了个假设:报错上提示了空指针异常,以及没有数据库连接,我就想到了一定是数据库的实现类的问题!
@Service
public class UserService {
@Autowired
JdbcTemplate jdbcTemplate;
public Integer addUser(User user){
return jdbcTemplate.update("insert into user values (?,?,?)",user.getId(),user.getUsername(),user.getAddress());
}
}
但是实现类没有问题啊!
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/lianxi
连接也没有问题!
那问题出在哪里?最后还是回到起点,想想注解和new实例既然都存在那一定是有意义的!
对比bean和数据库实现类发现了一个特点,bean里面只有单纯的方法没有其他的依赖注入,而实现类里有JdbcTemplate
的依赖注入,解密了:
@Autowired相当于setter,在注入之前,对象已经实例化,是在这个接口注解的时候实例化的;
而new只是实例化一个对象,而且new的对象不能调用注入的其他类
也就是说如果我new一个实现类,那么里面的依赖注入将全部失效!
简单例子:
1. 控制器
@controller
public class BusinessShopShoesController extends BaseController {
@Autowired
private ShoesService shoesService;//相当于setter,已经实例化
}
2.业务层
@service
public class ShoesService extends CrudService<ShoesDao, Shoes> {
@Autowired
ShoesModelDao shoesModelDao;
@Transactional(readOnly = false)
public Shoes get(int id)
{
return shoesModelDao.get(id);
}
}
此时如果1 中new一个service,那么就不能调用2 中的Dao了,因为DAO是依赖注入的