Skip to main content

依赖注入

了解依赖注入

Spring IoC容器

  1. 定义 bean 和装配

Spring会为使用以下注解的类创建 bean:

  • @Component 注解是定义 Spring bean 的最常用方法。其他注解具有与它们关联的更具体的上下文。
  • @Service 注解一般用在业务服务组件中。
  • @Repository 注解一般用在数据访问对象(DAO)组件中。
  1. 创建 Spring IoC 容器

可以通过下面两种方法创建 Spring IoC 容器:

  • Bean 工厂
  • 应用程序上下文
info

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