Spring - 依赖注入:构造函数注入、set方法注入和注解注入

1.2 依赖注入(Dependency Injection)

依赖注入的数据类型:

  1. 基本类型和String类型

  2. bean类型

  3. 复杂类型/集合类型

依赖注入的三种方式:

  1. 使用构造函数提供

  2. 使用set方法提供

  3. 使用注解方式提供

1.2.1 通过构造函数实现依赖注入

当java类中写了自己的构造函数(如下面所给代码,构造函数有三个参数),则可以通过构造函数的方式实现依赖注入,这个时候需要标签bean中的constructor-arg标签来实现每个参数的赋值。

标签:constructor-arg

属性

  1. name:用于给指定构造函数的指定形参赋值

  2. type:用于给指定构造函数中指定形参类型的形参赋值

  3. index:用于给指定构造函数中指定索引位置的形参赋值,索引从0开始

  4. value:用于给基本类型和String类型的形参赋实际值

  5. ref:用于给其他类型的形参赋实际值(IoC核心容器中定义的bean对象)

下面代码实现了利用构造函数方式完成依赖注入,AccountServiceImpl类有一个有三个参数的构造函数,在bean.xml中配置实现对三个参数赋值,创建AccountServiceImpl类的bean对象。

public class AccountServiceImpl implements IAccountService {
    private String name;
    private Integer i;
    private Date date;
​
    // 构造函数,有三个参数
    public AccountServiceImpl(String name, Integer i, Date date) {
        this.name = name;
        this.i = i;
        this.date = date;
    }
}
<!-- 通过构造函数来完成注解 -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    <!-- 通过name属性对构造函数中“name”参数进行赋值(String类型) -->
    <constructor-arg name="name" value="hugh"></constructor-arg>
    <!-- 通过type属性对构造函数中参数类型为Integer的参数进行赋值(基本类型) -->
    <constructor-arg type="java.lang.Integer" value="23"></constructor-arg>
    <!-- 通过index属性对构造函数中第2个参数进行赋值(bean对象),并利用ref属性引用其他bean对象 -->
    <constructor-arg index="2" ref="date_now"></constructor-arg>
</bean>
​
<bean id="date_now" class="java.util.Date"></bean>

需要注意,基本类型和String类型可直接通过value属性赋值,bean类型需要通过ref属性来引用IoC容器中的其他bean对象,而复杂类型/集合类型不可以通过valueref属性进行赋值,也就是复杂类型/集合类型不可通过构造函数注入(在1.2.2节中说明)。

1.2.2 通过set方法实现依赖注入

上面已经指出,复杂类型/集合类型不可通过构造函数注入,所以需要通过set方法注入。下面代码中的AccountServiceImpl类有5个复杂类型的类成员,对应有5个set方法,在bean.xml中用标签bean中的property标签,来对这5个类成员进行赋值。

标签:property

属性

  1. name:需要与set方法名一致,用于指定set方法

property中的标签:array, list, set, map, props,对应类成员类型

public class AccountServiceImpl implements IAccountService {
    private String[] strArray;      
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Properties prop;
​
    public void setStrArray(String[] strArray) {
        this.strArray = strArray;
    }
​
    public void setList(List list) {
        this.list = list;
    }
​
    public void setSet(Set set) {
        this.set = set;
    }
​
    public void setMap(Map map) {
        this.map = map;
    }
​
    public void setProp(Properties prop) {
        this.prop = prop;
    }
}
<!--  2、set方法注入
            构造函数注入方式不能注入复杂/集合类型,需要使用set方法注入
            数组形式:Array, List, Set
            键值对形式:Map, Properties
    -->
<bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
    <property name="strArray">
        <!-- strArray = ["AAA", "BBB", "CCC"] -->
        <array>
            <value>AAA</value>
            <value>BBB</value>
            <value>CCC</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>l</value>
            <value>i</value>
            <value>s</value>
            <value>t</value>
        </list>
    </property>
    <property name="set">
        <set>
            <value>s</value>
            <value>e</value>
            <value>t</value>
        </set>
    </property>
    <property name="map">
        <!-- map = {"key1": value1, "key2": value2} -->
        <map>
            <entry key="key1" value="value1"></entry>
            <entry key="key2">
                <value>value2</value>
            </entry>
        </map>
    </property>
    <property name="prop">
        <!-- prop = {"key1": properties} -->
        <props>
            <prop key="key1">properties</prop>
        </props>
    </property>
</bean>

1.2.3 通过注解实现依赖注入

1.2.3.1 对象注入通过注解实现,扫描配置通过bean.xml实现

用以下几个注解来告知spring那些java类需要创建bean对象

@Component

     作用:把当前类对象存入spring容器中
     属性:
         value:用于指定bean的id,默认为当前类名(首字母小写)

@Controller:一般用在表现层(作用与Component一样)

@Service:一般用在业务层(作用与Component一样)

@Repository:一般用在持久层(作用与Component一样)

另外需要配置bean.xml,需要注意两个部分:

  1. 需要修改命名空间

  2. 告知spring在创建IoC容器时要扫描的包

@Component("accountService")
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void saveAccount(){
        accountDao.saveAccount();
    }
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
​
    <!--告知spring在创建IoC容器时要扫描的包-->
    <context:component-scan base-package="com.itheima"></context:component-scan>
​
</beans>

另外,当需要对类中的成员变脸注入数据时,可以Autowired,Qualifier,Resource和Value实现,其中,Autowired,Qualifier和Resource用于注入bean类型的数据,Value用于注入基本类型和Stirng类型的数据,集合类型的数据只能通过xml注入。

@Autowired
    作用:自动按照类型注入
        1)IoC容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
        2)IoC容器中没有任何bean对象的类型和要注入的变量类型匹配,则报错
        3)IoC容器中有多个bean对象类型和要注入的变量类型匹配,首先查看是否有变量名称与bean对象id一致的bean对象,如果有则注入,没有则报错
    出现位置:可以是变量上,也可以是方法上
    细节:在使用注解注入时,set方法就不是必须的了

@Qualifier
    作用:在按照类中注入的基础之上,再按照名称注入
        1)给类成员注入时需要和Autowired一起使用
        2)给类方法参数注入时可单独使用???
    属性:
        value:用于指定bean的id

@Resource
    作用:直接按照bean的id注入,可单独使用
    属性:
        name:指定bean对象的id

@Value
    作用:用于注入基本类型和String类型的数据
    属性:
        value:用于指定数据的值,可以使用spring中SeEL(spring的EL表达式)

可通过注解Bean将当前方法的返回值作为bean对象存入spring容器中

@Bean
    作用:把当前方法的返回值作为bean对象存入spring容器中
    属性:
        name:指定bean的id,默认为方法名
    当使用Bean注解配置方法时,如果方法有参数,spring框架会从spring容器中查找有没有可用的bean对象, 查找方式和Autowired一样

@Bean(name = "runner")  // createQueryRunner方法的返回值存入spring容器中,id为“runner”
@Scope("prototype")     // 多例模式
public QueryRunner createQueryRunner(DataSource dataSource){
    return new QueryRunner(dataSource);
}

1.2.3.2 完全通过注解实现依赖注入(不使用xml)

如果想完全通过注解的形式(不使用xml)来实现依赖注入,我们需要新建一个spring配置类,其作用与bean.xml一致,并使用以下两个注解。

@Configuration
    作用:指定当前类为配置类

@ComponentScan
    作用:指定spring容器创建时,要扫描的包
    属性:
        basePackage/value:指定要扫描的包

@Configuration      // 指定当前类为配置类
@ComponentScan(basePackages = "com.itheima")    // 指定spring容器创建时,要扫描的包
public class SpringConfiguration {
​
}

这里需要引入两个新的注解:ConfigurationComponentScan。这里Configuration的作用是指定当前类为配置类,即bean.xml的作用;另外,我们需要告知spring在创建IoC容器时要扫描的包,这就需要ComponentScan来实现,即实现了bean.xml中的配置:

<!--告知spring在创建IoC容器时要扫描的包,配置所需要的标签不是在beans的约束中,
    而是以一个context的名称空间中 -->
<context:component-scan base-package="com.itheima"></context:component-scan>

另外,获取spring容器的方式也需要改变:

ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

这样我们就完成了完全使用注解的形式来实现依赖注入。

同时,我们可以有多个配置类,比如SpringConfiguration类为主配置类,jdbcConfiguration类为其中一个关于jdbc的配置类,这个时候就可以通过Import注解实现。

@Import 作用:导入其他配置类,有Import注解的是主配置类,导入的是子配置类 属性: value:指定其他配置类的字节码

@Configuration
@ComponentScan(basePackages = "com.itheima")
@Import(value = jdbcConfiguration.class)
@PropertySource(value = "classpath:jdbcConfig.properties")
public class SpringConfiguration {
​
​
}

 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring提供了几种依赖注入的方式。其中一种方式是自动装配,它可以通过上下文自动寻找bean并为其配置属性。这种方式可以减少手动配置的工作量,提高开发效率。另一种方式是使用反射来调用bean的默认构造函数实例化对象,并通过set方法注入属性值。这样可以实现bean的依赖注入。此外,Spring还提供了工厂方法的功能,可以通过工厂注入的方式来进行Spring依赖注入。工厂类可以屏蔽目标类的实例化步骤,调用者甚至不需要指定具体的目标类是什么。这种方式在一些遗留系统或第三方类库中还是会使用到。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Bean自动装配,注解](https://blog.csdn.net/weixin_41709536/article/details/108609172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Spring框架学习教程,详解Spring注入bean的几种方式](https://blog.csdn.net/Java___interview/article/details/120550945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值