当前位置:首页 > 技术 > 正文内容

Spring 框架中 Setter 注入与构造函数注入的实现

访客 技术 2026年8月1日 1

Setter 注入(Setter Injection)

Setter 注入是通过类的公共 Setter 方法来实现依赖关系的配置。这种方式允许在对象实例化后灵活地更改依赖关系。

XML 配置文件 (app-config.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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 使用 p 命名空间简化 Setter 注入 -->
    <bean id="displayer" 
          class="com.example.spring.xml.ConsoleDataDisplayer"
          p:dataSource-ref="source"/>

    <bean id="source" 
          class="com.example.spring.xml.DefaultContentSource"/>
</beans>

Java 接口定义

package com.example.spring;

public interface ContentSource {
    String provideContent();
}

public interface DataDisplayer {
    void display();
    void setDataSource(ContentSource source);
    ContentSource getDataSource();
}

Java 类实现

package com.example.spring.xml;

import com.example.spring.ContentSource;

public class DefaultContentSource implements ContentSource {
    @Override
    public String provideContent() {
        return "Hello, Spring Setter Injection!";
    }
}

package com.example.spring.xml;

import com.example.spring.ContentSource;
import com.example.spring.DataDisplayer;

public class ConsoleDataDisplayer implements DataDisplayer {
    private ContentSource dataSource;

    @Override
    public void display() {
        if (dataSource == null) {
            throw new IllegalStateException("The dataSource property must be initialized.");
        }
        System.out.println(dataSource.provideContent());
    }

    @Override
    public void setDataSource(ContentSource source) {
        this.dataSource = source;
    }

    @Override
    public ContentSource getDataSource() {
        return this.dataSource;
    }
}

启动程序

package com.example.spring;

import org.springframework.context.support.GenericXmlApplicationContext;

public class SpringRunner {
    public static void main(String[] args) {
        GenericXmlApplicationContext context = new GenericXmlApplicationContext();
        context.load("classpath:app-config.xml");
        context.refresh();

        DataDisplayer displayer = context.getBean("displayer", DataDisplayer.class);
        displayer.display();
        
        context.close();
    }
}

构造函数注入(Constructor Injection)

构造函数注入确保了 Bean 在创建时就处于完整状态。Spring 支持通过参数索引、类型或名称来解决构造函数歧义。

XML 配置文件 (constructor-config.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">

    <!-- 使用 c 命名空间进行构造函数注入 -->
    <bean id="customSource" 
          class="com.example.spring.xml.ConfigurableContentSource"
          c:text="Dynamic message via constructor"/>

    <!-- 演示类型匹配解决构造函数重载歧义 -->
    <bean id="typeDemo"
          class="com.example.spring.xml.ConstructorTypeResolver"> 
        <constructor-arg type="int" value="1024"/>
    </bean>
</beans>

Java 类实现

package com.example.spring.xml;

import com.example.spring.ContentSource;

public class ConfigurableContentSource implements ContentSource {
    private final String text;

    public ConfigurableContentSource(String text) {
        this.text = text;
    }

    @Override
    public String provideContent() {
        return text;
    }
}

package com.example.spring.xml;

import org.springframework.context.support.GenericXmlApplicationContext;

public class ConstructorTypeResolver {
    private String val;

    public ConstructorTypeResolver(String val) {
        System.out.println("String constructor triggered");
        this.val = val;
    }

    public ConstructorTypeResolver(int val) {
        System.out.println("Integer constructor triggered");
        this.val = "Value: " + val;
    }

    @Override
    public String toString() {
        return val;
    }

    public static void main(String[] args) {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.load("classpath:constructor-config.xml");
        ctx.refresh();

        ConstructorTypeResolver resolver = ctx.getBean("typeDemo", ConstructorTypeResolver.class);
        System.out.println("Result: " + resolver);

        ContentSource source = ctx.getBean("customSource", ContentSource.class);
        System.out.println("Source output: " + source.provideContent());
        
        ctx.close();
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。