文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Sprin如何控制反转和依赖注入

2023-06-29 06:07

关注

本篇内容主要讲解“Sprin如何控制反转和依赖注入”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Sprin如何控制反转和依赖注入”吧!

控制反转的类型

控制反转(IOC)旨在提供一种更简单的机制,来设置组件的依赖项,并在整个生命周期管理这些依赖项。通常,控制反转可以分成两种子类型:依赖注入(DI)和依赖查找(DL),这些子类型各自又可以被进一步分解为 IOC 服务的具体实现

1. 依赖查找

1.1 依赖拉取

依赖拉取(Dependency Pull),即根据需要,从注册表中提取依赖项,以下代码显示了基于 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 中,查找是针对管理资源的容器执行的,这个容器通常由应用程序服务器或框架(Tomcat、JBoss、Spring)提供,比如以下代码显示了一个提供依赖查找服务的容器接口

public interface Container {    // 根据key获取相应的依赖项    Object getDependency(String key);}

CDL 通过让组件实现以下代码接口来进行工作

public interface ManagedComponent {    void performLookup(Container container);}

组件需要实现该接口,当容器准备好将依赖项传递给组件时,会依次调用每个组件的 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 构造函数注入

当在组件的构造函数中提供依赖项时,就会发生构造函数依赖注入

public class ConstructorInjection {    private Dependency dependency;    public ConstructorInjection(Dependency dependency) {        this.dependency = dependency;    }    @Override    public String toString() {        return dependency.toString();    }}
2.2 setter 函数注入

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)的注入类型,在后面学习使用 @Autowire 注解进行自动装配时将介绍该注入类型

Spring 中的控制反转

1. Bean 和 BeanFactory

Spring 的依赖注入容器的核心是 BeanFactory,它负责管理组件,包括依赖项以及它们的生命周期。如果我们想获得一个组件(Bean),就必须创建一个实现了 BeanFactory 接口的实例,并对其进行配置

虽然 BeanFactory 可以通过编程方式配置,但更常见的做法是使用某种配置文件在外部对其进行配置。Bean 配置可以由实现 BeanDefinition 接口的类的实例来表示,对于任何实现了 BeanDefinitionReader 接口的 BeanFactory 实现类来说,都可以使用 PropertiesBeanDefinitionReader 或 XmlBeanDefinitionReader 从配置文件读取 BeanDefinition 数据

定义一组接口:

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实现之一        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 服务外,还提供其他如事务和 AOP 等服务。在开发基于 Spring 的应用程序时,建议通过 ApplicationContext 接口与 Spring 交互

2. 设置 Spring 配置

2.1 XML 配置

对于 XML 配置,需要声明应用程序需要的由 Spring 提供的名称空间基础信息,下面所示配置仅声明用于定义 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 注解配置

要想在应用程序使用 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 容器直接调用来实例化 bean,bean 名称与用于创建它的方法的名称相同

@Configurationpublic class HelloWorldConfiguration {    @Bean    public MessageProvider provider() {        return new HelloWorldMessageProvider();    }    @Bean    public MessageRender render() {        StandardOutMessageRender render = new StandardOutMessageRender();        render.setMessageProvider(provider());        return render;    }}

如果想从该类中读取配置信息,需要一个不同的 ApplicationContext 实现

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. 构造函数注入

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>

使用注解方式

@Servicepublic class ConfigurableMessageProvider implements MessageProvider {    private String message;    @Autowired    public ConfigurableMessageProvider(            @Value("hello world") String message) {        this.message = message;    }    @Override    public String getMessage() {        return null;    }}

到此,相信大家对“Sprin如何控制反转和依赖注入”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯