在Spring中,对象无需自己查找或创建与其关联的其他对象,而是由容器进行对象的“装配”,这就是Spring中依赖注入的本质。我们可以通过在代码中加入一些注解或配置自动装配Bean,实现自动化装配需要以下两步:
- 创建Bean并能在容器中注册
- 自动满足Bean之间的依赖
创建Bean并能在容器中注册
要创建能在容器中被发现的Bean,首先要在对应的类上使用@Component
(或@Controller
、@Repository
、@Service
)注解,使其称为一个Spring的Bean,其名称为类名。 例如我们将@Service
注解加到如下实现类上
@Service
public class EmployeeServiceImpl implements EmployeeService {
// ...
}
在查看Spring容器中加载了哪些类
@Test
public void getAllBeans() {
String[] beans = applicationContext.getBeanDefinitionNames();
for (String beanName : beans) {
Class<?> beanType = applicationContext.getType(beanName);
System.out.println("BeanName:" + beanName);
System.out.println("Bean的类型:" + beanType);
System.out.println("Bean所在的包:" + beanType.getPackage());
}
}
得到了如下的输出
BeanName:employeeServiceImpl
Bean的类型:class com.meituan.finance.account.biz.impl.EmployeeServiceImpl
Bean所在的包:package com.meituan.finance.account.biz.impl
可以发现Bean的名称默认为类名的小驼峰命名。 我们也可以,通过使用@Service("empService")
或Named("empService")
自定义Bean的名称为empService
当bean生成之后我们需要让Spring容器能够在启动时发现并进行管理,就需要启用组件扫描 使用@ComponentScan
注解可以启用Bean组件的扫描,默认情况下扫描所在类相同的包,或者在XML中进行配置
<context:component-scan base-package="com.meituan.finance.account"/>
自动满足Bean之间的依赖
Spring提供了@Autowried
注解用于进行Bean的自动装配,可以用于属性、构造方法和set方法上。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor
后置处理器,当容器扫描到@Autowied
、@Resource
(CommonAnnotationBeanPostProcessor
后置处理器处理的)或@Inject
时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性 在使用@Autowired
时,首先在容器中查询对应类型的bean
- 如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据
- 如果查询的结果不止一个,那么@Autowired会根据名称来查找。
- 如果查询的结果为空并且required=false(more),那么会抛出异常。
Spring官方推荐将其应用在构造方法上,定义一个全参的构造方法后,对其加上@Autowired
注解,实际上这个注解可以省略:
当一个类只有一个构造函数时,可以省略
@Autowired
的注解。
对构造方法加入注解,有以下优点
- 允许声明不可变域,即使用
final
修饰。 - 容易遵循单一职责设计原则。
- 注入的顺序更靠前
Java变量的初始化顺序:
- 静态变量或静态语句块
- 实例变量或初始化语句块
- 构造方法
- @Autowired装配的对象