前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2-Spring配置文件与依赖注入

2-Spring配置文件与依赖注入

作者头像
Ywrby
发布2022-10-27 13:30:58
2250
发布2022-10-27 13:30:58
举报
文章被收录于专栏:YwrbyYwrby

Spring配置文件

Bean标签基本配置

用于配置对象交由Spring来创建,默认情况下调用的是类中的无参构造函数,没有无参构造的情况下不能创建成功

基本属性
  • id:Bean实例在Spring中的唯一标识
  • class:Bean的全限定名称

Bean标签范围配置

scope属性

取值范围

说明

singleton

默认值,单例的

prototype

多例的

request

web项目中,Spring创建一个对象并将对象存入request域内

session

web项目中,Spring创建一个对象并将对象存入session域内

global session

web项目中,应用在Portlet环境,如果没有Portlet环境,global session相当于session

这里单例是指每次创建出的Bean对象都是同一个对象,而多例则表示每次创建的都是全新的不同的Bean对象

示例

代码语言:javascript
复制
<!--单例的-->
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" scope="singleton"></bean>
<!--多例的-->
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" scope="prototype"></bean>

测试

代码语言:javascript
复制
/**
 * 测试scope属性
 */
@Test
public void userDaoTest(){
    //指定配置文件
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //通关配置文件与ID获取实例
    UserDao dao1= (UserDao) context.getBean("userDao");
    UserDao dao2= (UserDao) context.getBean("userDao");
    //输出两个对象的地址即可判断是否两次创建为同一对象
    System.out.println(dao1);
    System.out.println(dao2);
}
singleton与prototype的区别

当scope取值为singleton时,Bean实例化的个数始终是一个,并且实例化的时机是在Spring核心文件(配置文件)被加载时

当scope取值为prototype时,Bean实例化的个数是多个,此时实例化的时机不是核心文件加载,而是在每次调用getBean方法时创建

Bean声明周期的配置

  • init-method:指定初始化方法,在对象创建时被调用
  • destroy-method:指定销毁方法,在对象被销毁时调用
代码语言:javascript
复制
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
代码语言:javascript
复制
public class UserDaoImpl implements UserDao {

    public void init(){
        System.out.println("执行初始化...");
    }

    public void destroy(){
        System.out.println("执行销毁...");
    }

    public void save() {
        System.out.println("Save Running...");
    }
}

Spring依赖注入

概念

依赖注入(Dependency Injection)是Spring框架核心IOC的具体实现

Bean对象的注入(引用数据类型的注入)

依赖注入的主要目的还是解耦,主要利用的原理就是控制反转,即将构造对象这个【控制】交给了第三方Spring来进行操作

我们在实际的项目开发中,必然涉及到对多个对象的构造与控制,而我们许多的对象已经预定义在Spring容器中(那些已经在配置文件中定义的对象)。

此时假如我们需要在某个Spring容器中已有的对象A内调用另一个同样已经在Spring容器中定义的对象B,一般情况我们会直接在对象A中加载配置文件,利用Spring获取对象B,然后再操作获取到的对象

这种情况下假如我们需要修改代码,就需要到所有操作配置文件获取对象B的方法内进行修改,直接导致了代码耦合度变高

代码语言:javascript
复制
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        //UserService与UserDao都是定义在Spring容器中的对象
        //这里在UserService的save方法中利用配置文件获取了UserDao对象
        //这也就导致了代码耦合度很高,不便于复用和修改
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao dao= (UserDao) context.getBean("userDao");
        dao.save();
    }
}

要解决这种问题就可以利用依赖注入,第一种方式是set方法注入,第二种是构造函数注入

set方法注入

即通过在配置文件中提前配置,使得在创建对象A时调用指定的set方法将对象B直接传入对象A内部,这样的注入方式保证了对象B没有在对象A的方法中进行实例化,而是作为参数直接传入A内部,需要使用对象B时直接使用传入的对象即可。需要修改代码时只需要对配置文件进行修改即可

首先在被传入的Bean中定义传入参数的set方法,并且定义成员变量用于接收传入的参数,修改调用对象B的函数,直接利用成员变量进行操作即可

代码语言:javascript
复制
public class UserServiceImpl implements UserService {
    private UserDao dao;  //定义成员变量

    //定义set方法,用于其他对象的传入
    public void setDao(UserDao dao) {
        this.dao = dao;
    }

    @Override
    public void save() {
        //修改成员方法,可以直接利用成员变量进行操作
        //省去了对配置文件的使用,降低了代码耦合度
        dao.save();
    }
}

然后修改配置文件,指定在创建UserService时调用指定的set方法注入相关参数(利用property标签进行指定 其中name是set方法后面的后缀并首字母小写,例如setDao方法,这里就传入dao,setUserService方法就传入userService ,ref是要传入的Spring容器中对象的ID)

代码语言:javascript
复制
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" ></bean>
<bean id="userService" class="cn.ywrby.service.impl.UserServiceImpl" >
    <property name="dao" ref="userDao"></property>
</bean>

测试用例:

代码语言:javascript
复制
/**
 * 测试依赖注入
 */
@Test
public void userServiceTest(){
    //指定配置文件
    ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //通关配置文件与ID获取实例
    UserService service= (UserService) context.getBean("userService");
    //执行方法
    service.save();
}

P命名空间注入

这种注入方式本质还是set方法注入,只是通过利用P命名空间,简化了配置方法

在配置时首先需要定义P命名空间(第三行即定义P命名空间)

代码语言:javascript
复制
<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命名空间的属性直接定义注入方法

代码语言:javascript
复制
<bean id="userService" class="cn.ywrby.service.impl.UserServiceImpl" p:dao-ref="userDao"></bean>
构造函数注入

构造函数注入就是在创建对象A时调用对象A的有参构造函数,将指定的对象B作为参数注入对象A中

首先需要在被注入的对象中创建有参构造

代码语言:javascript
复制
public class UserServiceImpl implements UserService {
    private UserDao dao;  //定义成员变量

    //定义有参构造
    public UserServiceImpl(UserDao dao) {
        this.dao = dao;
    }

    public UserServiceImpl(){}

    @Override
    public void save() {
        //修改成员方法,可以直接利用成员变量进行操作
        //省去了对配置文件的使用,降低了代码耦合度
        dao.save();
    }
}

然后在配置文件中声明要调用有参构造,并指定传入的对象在Spring容器中的ID(利用constructor-arg标签指定要传入的参数,name属性表示的是传入的对象命名,ref属性是传入参数在Spring容器中的ID)

代码语言:javascript
复制
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" ></bean>
<bean id="userService" class="cn.ywrby.service.impl.UserServiceImpl" >
    <constructor-arg name="dao" ref="userDao"></constructor-arg>
</bean>

普通数据类型的注入

在使用中,我们除了可能注入Spring中已经定义的引用数据类型,也有可能需要注入普通类型数据

代码语言:javascript
复制
public class UserDaoImpl implements UserDao {

    //定义普通数据类型的成员变量
    private int num;
    private String name;

    //定义set方法
    public void setNum(int num) {
        this.num = num;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void save() {
        System.out.println(name+" : "+num);
    }
}

修改配置文件

代码语言:javascript
复制
<bean id="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" >
    <property name="name" value="Leslie"/>
    <property name="num" value="18"/>
</bean>

因为此时注入的是普通数据类型,所以不需要通过ref属性指定ID,此时直接通过value属性将要注入的值传入

集合数据类型的注入

代码语言:javascript
复制
public class UserDaoImpl implements UserDao {

    //定义集合数据类型
    private List<String> nameList;
    private Map<String, User> userMap;
    private Properties properties;

    //定义set方法
    public void setNameList(List<String> nameList) {
        this.nameList = nameList;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void save() {
        System.out.println(nameList);
        System.out.println(userMap);
        System.out.println(properties);
    }
}

以下是集合数据类型注入时配置文件的配置方式

可以看到List类型注入时只需要定义value标签即可,标签体内传注入的值

Map类型在注入时需要利用entry标签传入键和值,键和值都可以使用引用类型或普通类型,引用类型只需要在后面加“-ref”即可

properties类型注入时和Map类似,也需要传入键和值,但是键是通过key属性传入的,值是直接写在标签体中的

代码语言:javascript
复制
<?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="userDao" class="cn.ywrby.dao.impl.UserDaoImpl" >
        <property name="nameList">
            <list>
                <value>Leslie</value>
                <value>Ywrby</value>
            </list>
        </property>
        <property name="userMap">
            <map>
                <entry key="1" value-ref="user1"></entry>
                <entry key="2" value-ref="user2"></entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="p1">value1</prop>
                <prop key="p2">value2</prop>
            </props>
        </property>
    </bean>
    
    <bean id="user1" class="cn.ywrby.domain.User">
        <property name="name" value="Jessica"></property>
        <property name="addr" value="Peking"></property>
    </bean>
    
    <bean id="user2" class="cn.ywrby.domain.User">
        <property name="name" value="Lere"></property>
        <property name="addr" value="SJZ"></property>
    </bean>
    
    <bean id="userService" class="cn.ywrby.service.impl.UserServiceImpl" >
        <constructor-arg name="dao" ref="userDao"></constructor-arg>
    </bean>
</beans>

测试用例:

代码语言:javascript
复制
@Test
public void userDaoTest3(){
    //指定配置文件
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    //通关配置文件与ID获取实例
    UserDao dao= (UserDao) context.getBean("userDao");
    //执行方法
    dao.save();
}
/*
运行结果:
[Leslie, Ywrby]
{1=User{name='Jessica', addr='Peking'}, 2=User{name='Lere', addr='SJZ'}}
{p1=value1, p2=value2}
 */

其他配置文件的引入

实际开发过程中我们所需要的配置文件可能是十分巨大的,内容十分杂乱,如果都定义在一个配置文件中,可读性和复写性都大打折扣

这种情况下我们可以将配置文件进行按模块拆分,或其他方式进行拆分,只需要最后在主配置文件中利用import标签进行引入即可

代码语言:javascript
复制
<import resource="applicationContext-user.xml"/>
<import resource="applicationContext-userDao.xml"/>
<import resource="applicationContext-userService.xml"/>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring配置文件
    • Bean标签基本配置
      • Bean标签范围配置
      • Bean声明周期的配置
      • 概念
      • Bean对象的注入(引用数据类型的注入)
      • 普通数据类型的注入
      • 集合数据类型的注入
  • Spring依赖注入
  • 其他配置文件的引入
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档