Spring?控制反轉(zhuǎn)和依賴注入的具體使用
控制反轉(zhuǎn)的類型
控制反轉(zhuǎn)(IOC)旨在提供一種更簡單的機制,來設(shè)置組件的依賴項,并在整個生命周期管理這些依賴項。通常,控制反轉(zhuǎn)可以分成兩種子類型:依賴注入(DI)和依賴查找(DL),這些子類型各自又可以被進一步分解為 IOC 服務(wù)的具體實現(xiàn)
1. 依賴查找
1.1 依賴拉取
依賴拉?。―ependency Pull),即根據(jù)需要,從注冊表中提取依賴項,以下代碼顯示了基于 Spring 的依賴拉取
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),同樣屬于依賴查找的子類型,和依賴拉取有點類似,但在 CDL 中,查找是針對管理資源的容器執(zhí)行的,這個容器通常由應(yīng)用程序服務(wù)器或框架(Tomcat、JBoss、Spring)提供,比如以下代碼顯示了一個提供依賴查找服務(wù)的容器接口
public interface Container { // 根據(jù)key獲取相應(yīng)的依賴項 Object getDependency(String key); }
CDL 通過讓組件實現(xiàn)以下代碼接口來進行工作
public interface ManagedComponent { void performLookup(Container container); }
組件需要實現(xiàn)該接口,當容器準備好將依賴項傳遞給組件時,會依次調(diào)用每個組件的 performLookup()
方法,然后組件就可以使用 Container
接口查找所需的依賴項
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ù)注入
當在組件的構(gòu)造函數(shù)中提供依賴項時,就會發(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 容器通過 JavaBean 樣式的 setter 方法注入組件的依賴項
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 注解進行自動裝配時將介紹該注入類型
Spring 中的控制反轉(zhuǎn)
1. Bean 和 BeanFactory
Spring 的依賴注入容器的核心是 BeanFactory,它負責管理組件,包括依賴項以及它們的生命周期。如果我們想獲得一個組件(Bean),就必須創(chuàng)建一個實現(xiàn)了 BeanFactory 接口的實例,并對其進行配置
雖然 BeanFactory 可以通過編程方式配置,但更常見的做法是使用某種配置文件在外部對其進行配置。Bean 配置可以由實現(xiàn) BeanDefinition 接口的類的實例來表示,對于任何實現(xiàn)了 BeanDefinitionReader 接口的 BeanFactory 實現(xiàn)類來說,都可以使用 PropertiesBeanDefinitionReader 或 XmlBeanDefinitionReader 從配置文件讀取 BeanDefinition 數(shù)據(jù)
定義一組接口:
public interface Oracle { String output(); } public class OracleImpl implements Oracle { @Override public String output() { return "hello world"; } }
接下來我們來看一看,Spring 的 BeanFactory 如何被初始化并用于獲取 Bean 實例
public class XmlConfigWithBeanFactory { public static void main(String[] args) { // DefaultListableBeanFactory是Spring提供的兩個主要BeanFactory實現(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來獲取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 的一個擴展,除了 DI 服務(wù)外,還提供其他如事務(wù)和 AOP 等服務(wù)。在開發(fā)基于 Spring 的應(yīng)用程序時,建議通過 ApplicationContext 接口與 Spring 交互
2. 設(shè)置 Spring 配置
2.1 XML 配置
對于 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>
標記告訴 Spring 掃描代碼,從而找到 @Component
等注解注入的 bean,以及支持在指定包(及其所有子包)下使用 @Autowire
等注解的 bean
2.3 Java 配置
配置類使用 @Configuration
注解,并包含用 @Bean
注解的方法,這些方法由 IOC 容器直接調(diào)用來實例化 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; } }
如果想從該類中讀取配置信息,需要一個不同的 ApplicationContext 實現(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 配置來配置 setter 注入,需要在 <bean>
標記下指定 <property>
標記,為其注入一個依賴項
<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 方法添加一個 @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> 標記 --> <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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
舉例講解Java設(shè)計模式編程中Decorator裝飾者模式的運用
這篇文章主要介紹了Java設(shè)計模式編程中Decorator裝飾者模式的運用,裝飾者模式就是給一個對象動態(tài)的添加新的功能,裝飾者和被裝飾者實現(xiàn)同一個接口,裝飾者持有被裝飾者的實例,需要的朋友可以參考下2016-05-05Java中Collection集合常用API之?Collection存儲自定義類型對象的示例代碼
Collection是單列集合的祖宗接口,因此它的功能是全部單列集合都可以繼承使用的,這篇文章主要介紹了Java中Collection集合常用API?-?Collection存儲自定義類型對象,需要的朋友可以參考下2022-12-12Spring?Boot?詳細分析Conditional自動化配置注解
首先我們先了解一下@Conditional注解,@Conditional是Spring4新提供的注解,它的作用是按照一定的條件進行判斷,需要注入的Bean滿足給定條件才可以注入到Spring?IOC容器中2022-07-07SpringBoot2整合Redis實現(xiàn)讀寫操作
Redis,對于大家來說應(yīng)該不陌生,是經(jīng)常使用的開發(fā)技術(shù)之一。本文將結(jié)合實例代碼,介紹SpringBoot2整合Redis實現(xiàn)讀寫操作,感興趣的小伙伴們可以參考一下2021-07-07Java實現(xiàn)基礎(chǔ)銀行ATM系統(tǒng)
這篇文章主要為大家詳細介紹了Java實現(xiàn)基礎(chǔ)銀行ATM系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05skywalking分布式服務(wù)調(diào)用鏈路追蹤APM應(yīng)用監(jiān)控
這篇文章主要為大家介紹了skywalking分布式服務(wù)調(diào)用鏈路追蹤APM應(yīng)用監(jiān)控的功能使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-03-03Java 數(shù)據(jù)結(jié)構(gòu)之時間復(fù)雜度與空間復(fù)雜度詳解
算法復(fù)雜度分為時間復(fù)雜度和空間復(fù)雜度。其作用: 時間復(fù)雜度是度量算法執(zhí)行的時間長短;而空間復(fù)雜度是度量算法所需存儲空間的大小2021-11-11關(guān)于maven配置項目一直提示程序包不存在以及scope的坑
這篇文章主要介紹了關(guān)于maven配置項目一直提示程序包不存在以及scope的坑,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11