我们提供安全,免费的手游软件下载!
在本文中,我们将介绍
IoC
(控制反转)和
DI
(依赖注入)的概念,以及如何在
Spring
框架中实现它们。
控制反转是软件工程中的一个原则,它将对象或程序的某些部分的控制权转移给容器或框架。我们最常在面向对象编程的上下文中使用它。
与传统编程相比,传统编程中我们的自定义代码调用库,而IoC使框架控制程序的流程并调用我们的自定义代码。为了实现这一点,框架使用具有附加行为的抽象。如果我们想要添加自己的行为,我们需要扩展框架的类或插入自己的类。
这种架构的优点是:
IoC
,例如:策略设计模式、服务定位器模式、工厂模式和依赖注入(
DI
)。
依赖注入是一种我们可以用来实现
IoC
的模式,其中被反转的控制是设置对象的依赖项。
将对象与其他对象连接或将对象“注入”到其他对象中是由汇编程序而不是对象本身完成的。
下面是在传统编程中创建对象依赖关系的方法:
public class Store {
private Item item;
public Store() {
item =new ItemImpl1();
}
}
在上面的示例中,我们需要在
Store
类本身中实例化
Item
接口的实现。
通过使用
DI
,我们可以重写该示例,而不指定我们想要的
Item
的实现:
public class Store {
private Item item;
public Store(Item item) {
this.item = item;
}
}
在接下来的几节中,我们将看看如何通过元数据提供Item的实现。
IoC
和
DI
都是简单的概念,但它们对我们构建系统的方式有深刻的影响,因此值得充分理解。
IoC
容器是实现
IoC
的框架的常见特征。
在
Spring
框架中,接口
ApplicationContext
表示
IoC
容器。
Spring
容器负责实例化、配置和组装称为
bean
的对象,以及管理它们的生命周期。
Spring
框架提供了
ApplicationContext
接口的几个实现:
ClassPathXmlApplicationContext和FileSystemXmlApplicationContext
用于独立应用程序,以及
WebApplicationContext
用于Web应用程序。
为了组装
bean
,容器使用配置元数据,可以是
XML
配置或注释形式。
以下是手动实例化容器的一种方法:
ApplicationContext context
=newClassPathXmlApplicationContext("applicationContext.xml");
在上面的示例中,我们可以使用元数据设置
item
属性,然后容器将读取此元数据并在运行时使用它来组装
bean
。
在
Spring
中,可以通过构造函数、
setter
或字段来进行依赖注入。
在基于构造函数的依赖注入的情况下,容器将调用具有表示我们要设置的依赖项的参数的构造函数。
Spring
通过类型解决每个参数,然后按属性名称和索引进行消歧。让我们看看使用注释配置
bean
及其依赖项的配置:
@Configuration
public class AppConfig {
@Bean
public Item item1() {
return new ItemImpl1();
}
@Bean
public Store store() {
return new Store(item1());
}
}
@Configuration
注释表示该类是
bean
定义的源。我们也可以将其添加到多个配置类中。
我们在方法上使用
@Bean
注释来定义
bean
。如果我们没有指定自定义名称,则
bean
名称将默认为方法名称。
对于默认的
singleton
范围的
bean
,
Spring
首先检查是否已存在缓存的
bean
实例,仅在不存在时创建新实例。如果我们使用
prototype
范围,则容器为每个方法调用返回一个新的
bean
实例。
创建
bean
的另一种方式是通过
XML
配置:
对于基于
setter
的
DI
,容器将在调用没有参数的构造函数或没有参数的静态工厂方法来实例化
bean
之后调用我们类的
setter
方法。让我们使用注释创建此配置:
@Bean
public Store store() {
Store store =new Store();
store.setItem(item1());
return store;
}
我们也可以使用XML进行相同的bean配置:
我们可以将构造函数和
setter
类型的注入结合在同一个
bean
中。
Spring
文档建议将基于构造函数的注入用于必需的依赖项,将基于
setter
的注入用于可选的依赖项。
在基于字段的
DI
的情况下,我们可以通过带有
@Autowired
/
@Resource
注释的注释将依赖项注入其中:
public class Store {
@Autowired
private Item item;
}
在构造
Store
对象时,如果没有构造函数或
setter
方法将
Itembean
注入其中,容器将使用反射将
Item
注入
Store
中。
我们也可以使用
XML
来实现这一点。
这种方法可能看起来更简单、更清晰,但我们不建议使用它,因为它有一些缺点,例如:
setter
的注入更昂贵。
自动装配允许
Spring
容器通过检查已定义的
bean
来自动解决协作
bean
之间的依赖关系。
使用
XML
配置有四种自动装配
bean
的模式:
no
:默认值 - 这意味着不使用自动装配,我们必须显式地命名依赖项。
byName
:按属性名称进行自动装配,因此
Spring
将查找与需要设置的属性同名的
bean
。
byType
:类似于按名称进行自动装配,仅基于属性的类型。这意味着
Spring
将查找具有相同类型的属性来设置的
bean
。如果有多个
bean
具有该类型,则框架会抛出异常。
constructor
:基于构造函数参数进行自动装配,意味着
Spring
将查找具有与构造函数参数相同类型的
bean
。
例如,让我们通过类型创建具有依赖项
item
的
store
bean
。
public class AppConfig {
@Bean
public Item item() {
return new ItemImpl1();
}
@Bean(autowire = Autowire.BY_TYPE)
public Store store() {
return new Store();
}
}
请注意,自
Spring 5.1
起,
autowire
属性已弃用。
我们还可以使用
@Autowired
注释按类型注入
bean
:
public class Store {
@Autowired
private Item item;
}
如果存在相同类型的多个
bean
,则可以使用
@Qualifier
注释按名称引用
bean
:
public class Store {
@Autowired
@Qualifier("item1")
private Item item;
}
现在,让我们通过
XML
配置按类型自动装配
bean
:
接下来,让我们通过
XML
按名称将名为
item
的
bean
注入到
store
bean
的
item
属性中:
我们还可以通过构造函数参数或
setter
显式定义依赖关系来覆盖自动装配。
默认情况下,容器在初始化期间创建和配置所有单例
bean
。为了避免这种情况,我们可以在
bean
配置上使用值为
true
的
lazy-init
属性:
因此,只有在第一次请求它时,才会初始化
item1
bean
,而不是在启动时。这样做的优点是初始化时间更快,但缺点是我们在
bean
被请求之后才会发现任何配置错误,这可能是应用程序已运行数小时甚至数天之后。
相关资讯
热门资讯