Spring-IoC(XML配置文件形式)

目录

概述

配置文件加载bean(IoC入门)

IoC中设置依赖(DI入门)

Bean的作用范围

Bean的实例化方式

方式一:使用空参构造器(默认)

 方式二:静态工厂

方式三:实例工厂

方式四:Factory Bean(对"实例工厂的优化")

 Bean的生命周期

控制生命周期

关闭IoC容器的方式

 依赖注入的方式

setter方式注入

构造器注入

 依赖自动装配


概述

IoC(Inversion of control) 控制反转,是一种思想。

IoC思想:为了解耦,在程序中不直接new获得对象,而是由外部提供对象(控制反转)。如果我们直接通过new的方式获得对象,需要清楚所有的底层对象初始化过程进行依赖处理,才能进行逻辑处理,而通过IoC引入的对象(外部提供),我们通过依赖注入(DI)的方式进行依赖处理就行。

 spring技术对IoC思想进行了实现。称为 IoC容器

IoC容器从当IoC思想中的"外部",用来负责对象的创建、初始化等一系列工作,在IoC容器中的对象统称为bean。

DI(Dependency Injection)依赖注入

 在IoC容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。

使用对象不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系。

配置文件加载bean(IoC入门)

测试用的包结构 

1.使用spring-IoC我们需要导入坐标:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.18</version>
</dependency>

2.创建配置文件,在配置文件中加载bean

 3.在IoC中创建bean

 4.获取IoC中的bean

public class mainTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext();
        //通过设置的id获取bean
        UserDAO userDAO = (UserDAO) context.getBean("userDAO");
        //bean调用方法
        userDAO.save();
    }
}

IoC中设置依赖(DI入门)

目录结构 

userService中引用UserDAO,并且使用其中的方法。

(使用依赖注入形式,原始是new之后使用new的对象调用其中的方法)

1.引入 依赖

 

 2.设置set方法(相当于是一个入口)

 

 3.到配置文件中设置依赖映射(解决依赖)


<bean id="userServiceImpl" class="com.mh.service.UserServiceImpl">
    <!--配置依赖--注意ref,不是value-->
    <!--name值要和引入依赖时属性名相同-->
    <property name="userDAO" ref="userDAO"></property>
</bean>

<!--依赖加入bean-->
<bean id="userDAO" class="com.mh.dao.UserDAOImpl"></bean>

4.测试方法即可。

Bean的作用范围

 在IoC中定义的bean,默认为单例模式scope:singleton

 设置bean的方式:在<bean> 中添加属性scope

Bean的实例化方式

方式一:使用空参构造器(默认)

在上述案例中均使用此方式构造bean,使用了默认的空参构造器。

 方式二:静态工厂

方式三:实例工厂

跟静态工厂很相似,实例工厂是非静态的,所以需要先将工厂加载到IoC容器中。 

方式四:Factory Bean(对"实例工厂的优化")

 

 Bean的生命周期

提到bean的生命周期,也就是在bean创建时或销毁时做一些事情。

控制生命周期

方式一:使用配置(非标准化)

就是在类中声明两个方法,初始化和销毁的方法,将两个自定义的方法配置到<bean>中。

未控制声明周期时执行

测试代码

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//测试userDAO方法,无依赖,测试成功
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.save();

执行结果 

 设置声明周期的控制

在类中声明方法

public class UserDAOImpl implements UserDAO{

    @Override
    public void save() {
        System.out.println("UserDAO...");
    }

    //自定义初始化和销毁方法
    public void init(){
        System.out.println("初始化方法加载...");
    }

    public void destroy(){
        System.out.println("销毁方法加载...");
    }
}

将方法加载到配置中

 再次测试执行结果:

 会发现一个问题,两个方法,只有初始化方法执行,销毁的方法并没有生效。

方式二:使用接口(标准化)

使用两个接口,实现其中的方法,两个接口分别对应着初始化和销毁的方法。

public class UserDAOImpl implements UserDAO, InitializingBean, DisposableBean {

    @Override
    public void save() {
        System.out.println("UserDAO...");
    }
    
    //销毁方法
    @Override
    public void destroy() throws Exception {

    }
    
    //初始化方法(在属性之后执行)
    @Override
    public void afterPropertiesSet() throws Exception {
        
    }
}

执行测试方法,和方式一 一样:

 两种方法可以看出,只有初始化方法执行,销毁的方法没有被执行,也就是声明周期并没有在虚拟机关闭前自动的调用销毁方法,所以我们只能手动将IoC容器关闭,才会执行销毁方法。

关闭IoC容器的方式

1.手动关闭容器

具体使用:close()

测试代码

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//测试userDAO方法,无依赖,测试成功
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.save();
//手动关闭容器
context.close();

测试代码执行结果(销毁方法执行)

2.注册钩子 

测试代码 

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) context.getBean("userDAO");
userDAO.save();
context.registerShutdownHook();

 测试代码执行结果和手动关闭结果一致

手动关闭和注册钩子的方式说明:手动关闭需要考虑书写的位置,一般写到代码最后,而注册钩子则没有书写位置要求。

 依赖注入的方式

setter方式注入

引用数据类型 

setter注入,就是给需要的依赖设置set方法,包括基本数据类型和引用数据类型。

依赖:userDAO ,设置set方法

public class UserServiceImpl implements UserService{
    
    //引用数据类型
    private UserDAO userDAO;
    
    //设置set方法    
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    @Override
    public void save() {
        //在其中调用userDAO(依赖)
        userDAO.save();
        System.out.println("userService...");
    }
}

 配置依赖

<bean id="userDAO" class="com.mh.dao.UserDAOImpl"></bean>
<bean id="userServiceImpl" class="com.mh.service.UserServiceImpl">
    <property name="userDAO" ref="userDAO"></property>
</bean>

简单数据类型

 设置简单数据类型依赖,并且设置set方法

public class UserDAOImpl implements UserDAO {
    
    //设置简单数据类型依赖
    private String uname;
    
    //设置set方法
    public void setUname(String uname) {
        this.uname = uname;
    }
    
    @Override
    public void save() {
        System.out.println("UserDAO..." + uname);
    }
}

配置依赖

<bean id="userDAO" class="com.mh.dao.UserDAOImpl">
    <!--使用value属性赋值-->
    <property name="uname" value="Tom"/>
</bean>

构造器注入

类中设置简单数据类型和构造器

public class GoodsDAOImpl  implements GoodsDAO {

    int num;

    public GoodsDAOImpl(int num){
        this.num = num;
    }

    @Override
    public void save() {
        System.out.println("goods..." + num );
    }
}
<bean id="goodsDAO" class="com.mh.dao.GoodsDAOImpl">
	<constructor-arg name="num" value="100"/>
</bean>

类型装配

此方式存在紧耦合(属性名字需要一致),不利于使用。解决方式:使用类型进行装配

<bean id="goodsDAO" class="com.mh.dao.GoodsDAOImpl">
    <constructor-arg type="int" value="100"/>
</bean>

此方式解决了名字的耦合问题,但是存在:万一数据类型不唯一的情况就不可用。

比如存在两个int类型的情况。这种情况下:就可以使用索引进行装配。

索引装配

<bean id="goodsDAO" class="com.mh.dao.GoodsDAOImpl">
    <constructor-arg index="0" value="100"/>
</bean>

依赖注入的方式选择 

 依赖自动装配

IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

 自动装配的方式:

1.按类型装配

2.按名称装配

 自动装配特征

  • 自动装配用于引用类型依赖注入,不能简单类型进行操作。
  • 使用按类型装配时,必须保障容器中相容类型的bean唯一。
  • 使用按名称装配时,必须保障容器中具有指定名称的bean。
  • 自动装配优先级低于setter注入与构造器注入。两者使用可能会发生冲突导致报错。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mao.O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值