溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Sprin如何控制反轉(zhuǎn)和依賴注入

發(fā)布時(shí)間:2022-02-21 09:20:26 來(lái)源:億速云 閱讀:124 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“Sprin如何控制反轉(zhuǎn)和依賴注入”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Sprin如何控制反轉(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)?/h5>

    依賴?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ò)編程方式配置,但更常見(jiàn)的做法是使用某種配置文件在外部對(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ù)。在開(kāi)發(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;
        }
    }

    到此,相信大家對(duì)“Sprin如何控制反轉(zhuǎn)和依賴注入”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI