Spring IoC 依赖注入的实现方式

本文详细介绍了Spring框架中依赖注入的实现方式,包括setter方法、构造器、接口回调和注解,并通过XML配置示例和代码演示了如何在类中使用@Autowired注解。此外,还探讨了不同注入方式的优缺点和相关注解的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇,用 setter 方式举例说明了 Spring 中的依赖注入支持的数据类型

 

这篇,看看依赖注入的实现方式。

 

首先,bean 的配置文件可以通过 xml 和 properties 两种方式。其中 xml 是主流,properties 基本不用,具体实现方式:

  • setter 方法

  • 构造器

  • 接口回调

  • 注解

  • API

 

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">

    <bean id="ConstXiong" class="constxiong.impltype.User">
        <constructor-arg>
            <value>1</value>
        </constructor-arg>
        <property name="name" value="ConstXiong"/>
    </bean>

    <bean id="favorites" class="java.lang.String">
        <constructor-arg>
            <value>写代码、睡觉</value>
        </constructor-arg>
    </bean>

    <!-- 开启注解能力 -->
    <context:component-scan base-package="constxiong"/>

</beans>

 

bean 的类代码

package constxiong.impltype;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class User implements ApplicationContextAware {

    //构造方法注入
    private Integer id;
    public User(Integer id) {
        this.id = id;
    }
    // set 方法注入
    private String name;
    public void setName(String name) {
        this.name = name;
    }

    //实现接口 ApplicationContextAware 及其回调方法注入 applicationContextAware
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    // xml 开启注解能力
    // 使用 @Autowired 给属性字段注入
    @Autowired
    private String favorites;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", applicationContext=" + applicationContext +
                ", friend=" + favorites +
                '}';
    }
}

 

测试代码,包含 bean 通过 api 注册与注入

package constxiong.impltype;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 依赖注入的实现方式
 */
public class Test {

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring-dependency-injection-impltype.xml");
        User constxiong = (User)context.getBean("ConstXiong");
        System.out.println(constxiong);

        //api 构造、注入、组装、注册 bean
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();
        AbstractBeanDefinition userBeanDefinition = new RootBeanDefinition(User.class);
        //构造方法注入
        beanFactory.registerBeanDefinition("ApiUser", userBeanDefinition);
        ConstructorArgumentValues argValues = new ConstructorArgumentValues();
        argValues.addIndexedArgumentValue(0, 1);
        //set 方法注入
        userBeanDefinition.setConstructorArgumentValues(argValues);
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.addPropertyValue(new PropertyValue("name", "ApiUser"));
        userBeanDefinition.setPropertyValues(propertyValues);
        System.out.println(beanFactory.getBean("ApiUser"));
    }
}

 

结果打印

User{id=1, name='ConstXiong', applicationContext=org.springframework.context.support.ClassPathXmlApplicationContext@1a6c5a9e, started on Mon Jan 11 23:10:11 CST 2021, friend=写代码、睡觉}
User{id=1, name='ApiUser', applicationContext=org.springframework.context.support.ClassPathXmlApplicationContext@1a6c5a9e, started on Mon Jan 11 23:10:11 CST 2021, friend=写代码、睡觉}

 


代码加了注释很容易看懂,强调几点:

  • 注解的使用需要在 xml 里添加 context 的命名空间,context:component-scan 开启注解的能力,设置 bean 扫描路径。

  • setter 方法注入的缺点是可能放大了 bean 的修改权限、如果字段之间有依赖关系与校验逻辑 set 顺序不可控。

  • 构造方法注入的缺点是属性较多时构造方法参数配置较多,顺序易出错、对 null 处理灵活性较差、不利于子类继承与扩展。

  • 与注入的相关的注解除了示例中的 @Autowired,还包括 @Autowired + @Qualifier 指定 bean 名称注入,@Resource(name="") 指定 bean 名称注入,JSR250 规范;@Value 注入字符串、系统信息、配置文件信息、表达式等;@Inject JSR330规范。一般 @Autowired 使用最多,注解的使用都支持在属性字段上,有些也可以用在 setter 方法和构造方法上。

  • <bean> 标签还可以指定 autowire,自动绑定(Autowiring)的模式,这个配置也会影响依赖注入的结果。no:默认该值,不进行自动注入,需要手动配置要注入的 bean;byName:根据 bean 名称注入;byType:根据类型注入;constructor:根据构造方法加其参数注入。

  • 网上还有资料提到了静态工厂方法注入和实例工厂方法注入,个人觉得这两个只是 bean 的创建的方式,严格意义上还未到注入的范畴。

 

 


【Java学习资源】整理推荐

 

 


【Java面试题与答案】整理推荐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值