依赖注入
了解依赖注入
Spring IoC容器
- 定义 bean 和装配
Spring会为使用以下注解的类创建 bean:
@Component
注解是定义 Spring bean 的最常用方法。其他注解具有与它们关联的更具体的上下文。@Service
注解一般用在业务服务组件中。@Repository
注解一般用在数据访问对象(DAO)组件中。
- 创建 Spring IoC 容器
可以通过下面两种方法创建 Spring IoC 容器:
- Bean 工厂
- 应用程序上下文
Bean 工厂是 Spring IoC 所有功能(bean 生命周期和装配)的基础。基本上,应用程序上下文是 Bean 工厂的超集,并提供了企业环境中通常所需的其他功能。Spring 建议,除非应用程序上下文额外占用的少量内存至关重要,否则应在所有情况下使用应用程序上下文。
应用程序上下文可以采用 Java 配置或 XML 配置:
应用程序上下文的 Java 配置:
@Configuration
@ComponentScan(basePackages = { "com.mastering.spring" })
class SpringContext { }
@Configuration
注解此配置定义为 Spring 配置,@ComponentScan
注解告诉 Spring IoC 容器在哪些包搜索 bean。
通过 Java 配置启动应用程序上下文:
通过 AnnotationConfigApplicationContext
,使用 main
方法可启动应用程序上下文:
public class LaunchJavaContext {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringContext.class);
// ApplicationContext context = new ClassPathXmlApplicationContext("BusinessApplicationContext.xml"); XML配置创建应用程序上下文
BusinessService service = context.getBean(BusinessService.class);
}
}
容器托管bean
由容器托管的 bean,称为容器托管 bean(Container Managed Bean)。将创建和管理 bean 的任务分配给容器有以下好处:
- 由于类不负责创建依赖项,因此,它们之间为松散耦合关系,并且可以进行测试。这会优化设计并减少缺陷。
- 由于容器负责管理 bean,因此就能够以通用性更强的方式引入一些 bean 挂钩。横切关注点,如日志记录、事务管理和异常处理,都可以使用面向切面编程(AOP)与这些 bean 关联起来。这进一步提高了代码的可维护性。
依赖注入类型
常用的依赖注入共有两种类型:
setter 注入
setter注入用于通过 setter方法注入依赖项:
@Service
public class BusinessServiceImpl {
private DataService dataService;
@Autowired
public void setDataService(DataService dataService) {
this.dataService = dataService;
}
// 要使用 setter 注入不需要声明 setter 方法。如果对变量指定 @Autowired,Spring 就会自动使用 setter 注入:
@Autowired
private DateService dataService2;
}
Spring bean 作用域
@Service
@Scope("singleton")
public class BusinessServiceImpl implements BusinessService {}
可用于bean的作用域列表:
prototype
每次从Spring容器中请求bean时,都会创建一个新实例request
,session
,application
仅在 Spring Web 上下文中可用, 作用域分别是每个HTTP请求、每个Session会话、每个Web应用创建一个新实例
2.1.8 @Autowired注解详解
对依赖项使用@Autowired
时,如果找到多个或者找不到匹配项时都会导致自动装配失败。
如果找到多个匹配项,可以通过以下两种方式解决:
- 使用
@Primary
注解将其中一个候选项标记为首要使用的候选项(如果有多个@Primary
也会导致失败) - 对依赖项增加
@Qualifier
注解, 进一步限定自动装配
TODO 研究视图 viewResolver 依赖项集合如何实现
2.1.9 其他重要的Spring注解
@ScopedProxy
有时需要将作用域为请求或会话的bean注入单例bean中。在这类情况下,@ScopedProxy注解提供了将注入单例bean中的智能代理 |
@Component
@Service
@Controller
@Repository
@Component
注解是定义Spring bean的最常用方法。其他注解有与它们关联的更具体上下文:@Service
用于业务服务层@Repository
用于数据访问对象(DAO)@Controller
用于演示组件
@PostConstruct
对任何Spring bean,都可以使用@PostConstruct
注解来提供一个在构造函数后调用的方法。bean用依赖项完全初始化后,将调用此方法一次。在bean生命周期中,只调用一次此方法
@PreDestroy
对任何Spring bean,都可以使用@PreDestroy
注解来提供一个在销毁前调用的方法。只会在从容器中删除bean时调用此方法。此方法可用于释放任何由bean保留的资源
2.1.10 上下文和依赖注入
Spring支持在JSR-330中定义的标准注解(即Java EE引入的CDI), 在使用CDI之前需要引入依赖项:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
CDI注解 | 与Spring相比较 |
---|---|
@Inject | 与@Autowired 类似。一个不太明显的区别在于,@Inject 缺少所需的属性 |
@Named | @Named 类似于@Component 。它用于标识命名组件,还可用于通过与@Qualifier Spring注解类似的名称限定bean。如果多个候选项可用于自动装配一个依赖项,这时可以使用此注解 |
@Singleton | 类似于Spring注解@Scope ("singleton") |
@Qualifier | 类似于Spring中的同名注解—— @Qualifier |