Spring?控制反轉(zhuǎn)和依賴注入的具體使用
控制反轉(zhuǎn)的類型
控制反轉(zhuǎn)(IOC)旨在提供一種更簡(jiǎn)單的機(jī)制,來(lái)設(shè)置組件的依賴項(xiàng),并在整個(gè)生命周期管理這些依賴項(xiàng)。通常,控制反轉(zhuǎn)可以分成兩種子類型:依賴注入(DI)和依賴查找(DL),這些子類型各自又可以被進(jìn)一步分解為 IOC 服務(wù)的具體實(shí)現(xiàn)
1. 依賴查找
1.1 依賴?yán)?/h4>
依賴?yán)。―ependency Pull),即根據(jù)需要,從注冊(cè)表中提取依賴項(xiàng),以下代碼顯示了基于 Spring 的依賴?yán)?/p>
public class DependencyPull {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring/app-context.xml");
ctx.getBean("renderer", MessageRenderer.class);
}
}
1.2 上下文依賴查找
上下文依賴查找(contextualized dependency lookup,CDL),同樣屬于依賴查找的子類型,和依賴?yán)∮悬c(diǎn)類似,但在 CDL 中,查找是針對(duì)管理資源的容器執(zhí)行的,這個(gè)容器通常由應(yīng)用程序服務(wù)器或框架(Tomcat、JBoss、Spring)提供,比如以下代碼顯示了一個(gè)提供依賴查找服務(wù)的容器接口
public interface Container {
// 根據(jù)key獲取相應(yīng)的依賴項(xiàng)
Object getDependency(String key);
}CDL 通過(guò)讓組件實(shí)現(xiàn)以下代碼接口來(lái)進(jìn)行工作
public interface ManagedComponent {
void performLookup(Container container);
}組件需要實(shí)現(xiàn)該接口,當(dāng)容器準(zhǔn)備好將依賴項(xiàng)傳遞給組件時(shí),會(huì)依次調(diào)用每個(gè)組件的 performLookup() 方法,然后組件就可以使用 Container 接口查找所需的依賴項(xiàng)
public class ContextualizedDependencyLookup implements ManagedComponent {
private Dependency dependency;
@Override
public void performLookup(Container container) {
this.dependency = (Dependency) container.getDependency("myDependency");
}
@Override
public String toString() {
return dependency.toString();
}
}2. 依賴注入
2.1 構(gòu)造函數(shù)注入
當(dāng)在組件的構(gòu)造函數(shù)中提供依賴項(xiàng)時(shí),就會(huì)發(fā)生構(gòu)造函數(shù)依賴注入
public class ConstructorInjection {
private Dependency dependency;
public ConstructorInjection(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}2.2 setter 函數(shù)注入
Ioc 容器通過(guò) JavaBean 樣式的 setter 方法注入組件的依賴項(xiàng)
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}在 Spring 中,還支持另一種被稱為字段注入(field injection)的注入類型,在后面學(xué)習(xí)使用 @Autowire 注解進(jìn)行自動(dòng)裝配時(shí)將介紹該注入類型
Spring 中的控制反轉(zhuǎn)
1. Bean 和 BeanFactory
Spring 的依賴注入容器的核心是 BeanFactory,它負(fù)責(zé)管理組件,包括依賴項(xiàng)以及它們的生命周期。如果我們想獲得一個(gè)組件(Bean),就必須創(chuàng)建一個(gè)實(shí)現(xiàn)了 BeanFactory 接口的實(shí)例,并對(duì)其進(jìn)行配置
雖然 BeanFactory 可以通過(guò)編程方式配置,但更常見的做法是使用某種配置文件在外部對(duì)其進(jìn)行配置。Bean 配置可以由實(shí)現(xiàn) BeanDefinition 接口的類的實(shí)例來(lái)表示,對(duì)于任何實(shí)現(xiàn)了 BeanDefinitionReader 接口的 BeanFactory 實(shí)現(xiàn)類來(lái)說(shuō),都可以使用 PropertiesBeanDefinitionReader 或 XmlBeanDefinitionReader 從配置文件讀取 BeanDefinition 數(shù)據(jù)
定義一組接口:
public interface Oracle {
String output();
}
public class OracleImpl implements Oracle {
@Override
public String output() {
return "hello world";
}
}接下來(lái)我們來(lái)看一看,Spring 的 BeanFactory 如何被初始化并用于獲取 Bean 實(shí)例
public class XmlConfigWithBeanFactory {
public static void main(String[] args) {
// DefaultListableBeanFactory是Spring提供的兩個(gè)主要BeanFactory實(shí)現(xiàn)之一
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
// 使用XmlBeanDefinitionReader從XML文件讀取BeanDefinition信息
rdr.loadBeanDefinitions(new ClassPathResource("spring/xml-bean-factory-config.xml"));
// 使用在XML配置文件中配置的名稱oracle來(lái)獲取bean
Oracle oracle = (Oracle) factory.getBean("oracle");
System.out.println(oracle.getInfo());
}
}<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="oracle" name="oracle" class="com.example.OracleImpl"/>
</beans>
ApplicationContext 接口是 BeanFactory 的一個(gè)擴(kuò)展,除了 DI 服務(wù)外,還提供其他如事務(wù)和 AOP 等服務(wù)。在開發(fā)基于 Spring 的應(yīng)用程序時(shí),建議通過(guò) ApplicationContext 接口與 Spring 交互
2. 設(shè)置 Spring 配置
2.1 XML 配置
對(duì)于 XML 配置,需要聲明應(yīng)用程序需要的由 Spring 提供的名稱空間基礎(chǔ)信息,下面所示配置僅聲明用于定義 bean 的名稱空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provider" class="com.example.HelloWorldMessageProvider"/>
<bean id="render" class="com.example.StandardOutMessageRender"
p:messageProvider-ref="provider"/>
</beans>
2.2 注解配置
要想在應(yīng)用程序使用 Spring 的注解支持,需要在 XML 配置中聲明
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.example" />
</beans><context:component-scan> 標(biāo)記告訴 Spring 掃描代碼,從而找到 @Component 等注解注入的 bean,以及支持在指定包(及其所有子包)下使用 @Autowire 等注解的 bean
2.3 Java 配置
配置類使用 @Configuration 注解,并包含用 @Bean 注解的方法,這些方法由 IOC 容器直接調(diào)用來(lái)實(shí)例化 bean,bean 名稱與用于創(chuàng)建它的方法的名稱相同
@Configuration
public class HelloWorldConfiguration {
@Bean
public MessageProvider provider() {
return new HelloWorldMessageProvider();
}
@Bean
public MessageRender render() {
StandardOutMessageRender render = new StandardOutMessageRender();
render.setMessageProvider(provider());
return render;
}
}如果想從該類中讀取配置信息,需要一個(gè)不同的 ApplicationContext 實(shí)現(xiàn)
public class HelloWorldSpringAnnotated {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx
= new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
MessageRender render = ctx.getBean("render", MessageRender.class);
render.render();
}
}3. setter 注入
使用 XML 配置來(lái)配置 setter 注入,需要在 <bean> 標(biāo)記下指定 <property> 標(biāo)記,為其注入一個(gè)依賴項(xiàng)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provider" class="com.example.HelloWorldMessageProvider"/>
<bean id="render" class="com.example.StandardOutMessageRender">
<property name="messageProvider" ref="provider"/>
</bean>
</beans>
如果使用注解,只需要向 setter 方法添加一個(gè) @Autowired 注解
@Service("render")
public class StandardOutMessageRender implements MessageRender {
...
@Override
@Autowired
public void setMessageProvider(MessageProvider messageProvider) {
this.messageProvider = messageProvider;
}
}4. 構(gòu)造函數(shù)注入
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
public ConfigurableMessageProvider(String message) {
this.message = message;
}
@Override
public String getMessage() {
return null;
}
}使用 XML 方式注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="oracle" name="oracle" class="com.example.OracleImpl"/>
<!-- 使用 <constructor-arg> 標(biāo)記 -->
<bean id="messageProvider" class="com.example.ConfigurableMessageProvider">
<constructor-arg value="hello world" />
</bean>
<!-- 使用c名稱空間 -->
<bean id="provider" class="com.example.ConfigurableMessageProvider"
c:message="hello world"/>
</beans>
使用注解方式
@Service
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
@Autowired
public ConfigurableMessageProvider(
@Value("hello world") String message) {
this.message = message;
}
@Override
public String getMessage() {
return null;
}
}到此這篇關(guān)于Spring 控制反轉(zhuǎn)和依賴注入的具體使用的文章就介紹到這了,更多相關(guān)Spring 控制反轉(zhuǎn)和依賴注入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
記一次Feign中實(shí)現(xiàn)傳實(shí)體Bean的問(wèn)題
這篇文章主要介紹了記一次Feign中如何傳實(shí)體Bean的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java中checkbox實(shí)現(xiàn)跨頁(yè)多選的方法
最近做了一個(gè)項(xiàng)目其中遇到這樣的需求,要實(shí)現(xiàn)checkbox跨頁(yè)多選功能,經(jīng)過(guò)小編整理,順利解決,今天小編給大家分享Java中checkbox實(shí)現(xiàn)跨頁(yè)多選的方法,需要的的朋友參考下2017-01-01
詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則
這篇文章主要介紹了詳解Spring Cloud Gateway基于服務(wù)發(fā)現(xiàn)的默認(rèn)路由規(guī)則,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
Spring?Security?過(guò)濾器注冊(cè)脈絡(luò)梳理
這篇文章主要介紹了Spring?Security過(guò)濾器注冊(cè)脈絡(luò)梳理,Spring?Security在Servlet的過(guò)濾鏈中注冊(cè)了一個(gè)過(guò)濾器FilterChainProxy,它會(huì)把請(qǐng)求代理到Spring?Security自己維護(hù)的多個(gè)過(guò)濾鏈,每個(gè)過(guò)濾鏈會(huì)匹配一些URL,如果匹配則執(zhí)行對(duì)應(yīng)的過(guò)濾器2022-08-08
Spring Security Oauth2.0認(rèn)證授權(quán)教程
Spring Security實(shí)現(xiàn)用戶認(rèn)證、會(huì)話管理及授權(quán),支持Token等多方式,OAuth2.0用于分布式系統(tǒng)統(tǒng)一認(rèn)證,網(wǎng)關(guān)解析令牌并轉(zhuǎn)發(fā)請(qǐng)求2025-07-07
如何解決Maven無(wú)法拉取SNAPSHOT依賴問(wèn)題
在使用Maven管理項(xiàng)目時(shí),可能會(huì)遇到無(wú)法拉取SNAPSHOT版本依賴的問(wèn)題,這通常是因?yàn)镸aven默認(rèn)不支持直接拉取SNAPSHOT版本,遇到這樣的問(wèn)題,可以通過(guò)在項(xiàng)目的pom.xml文件中添加<repositories>標(biāo)簽,并配置啟用SNAPSHOT的倉(cāng)庫(kù)地址來(lái)解決2024-10-10

