枉玖

V1

2023/05/24阅读:12主题:默认主题

从零开始的SSM框架02-Spring中Bean的实例化与依赖注入

想要更好更炫酷的阅读体验,欢迎访问我的博客:https://wang-nine.github.io/ 点击下面的超链接快速访问

我的博客

本篇文章的地址

详细的描述了Spring中Bean的实例化与依赖注入。将会在以后的更新中逐渐更新我学习SSM框架的笔记,欢迎大家观看或者收藏。

Bean的实例化

构造方法

Spring创建Bean的时候调用无参构造。(有参构造会报错,私有无参也可以,底层使用了反射)

注意:Spring中的报错从下向上看,直到找到有用的信息。

注意:若不存在无参构造方法,会抛出异常:BeanCreationException

添加无参构造后: 运行结果:

静态工厂

创建对象不需要自己new,创建一个工厂创建对象达到解耦的效果

样例代码:

package wang.factory;

import wang.dao.Dao;
import wang.dao.impl.DaoImpl;

public class DaoFactory {
    public static Dao getDao() {
     System.out.println("factory set up ...");
        return new DaoImpl();
    }
}

配置文件添加如下代码:

<bean id="daoFactory" class="wang.factory.DaoFactory" factory-method="getDao"/>

主函数:

package wang;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import wang.dao.Dao;

public class App3 {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Dao dao = (Dao) ctx.getBean("daoFactory");
        dao.save();
    }
}

运行结果:

实例工厂

工厂代码同上

配置文件修改为如下代码:

<bean id="daoFactorytemp" class="wang.factory.DaoFactory"/>                 <!-- 创建工厂bean -->
<bean id="daoFactory" factory-bean="daoFactorytemp" factory-method="getDao"/>
<!-- factory-bean指定工厂bean -->

第一行为一个无用的bean,改良后即为第四种方法

主函数不变

运行结果:

FactoryBean(重要!)

在第三种方法存在两个问题 一、factory-bean属性使用时会创建一个无用的Bean 二、factory-method属性方法名不固定,非动态实现

因此,对此方法做了改良

factory实现一个接口FactoryBean

工厂代码

package wang.factory;

import org.springframework.beans.factory.FactoryBean;
import wang.dao.Dao;
import wang.dao.impl.DaoImpl;

public class DaoFactoryBean implements FactoryBean<Dao{
    // 代替原始实例工厂创建对象的方法
    @Override
    public Dao getObject() throws Exception {
        return new DaoImpl();
    }
    // 得到Bean的类型
    @Override
    public Class<?> getObjectType() {
        return Dao.class;
    }
    // 设置Bean是否单例子,return true为单例,false为非单例
    // 该方法一般不重写
    /*@Override
    public boolean isSingleton() {
        return true;
    }*/

}

配置文件修改为如下代码:

<bean id="daoFactory" class="wang.factory.DaoFactoryBean"/>

主函数不变

运行结果:

补充:Bean的生命周期

控制生命周期
方法一:

控制方法代码:

public static DaoImpl implements Dao {
    public void save() {
        System.out.println("Dao save ... ")
    }
    public void init() {
        System.out.println("Dao init ... ")
    }
    public void destroy() {
        System.out.println("Dao destroy ... ")
    }
}

配置控制方法:

<bean id="Dao" class="wang.dao.impl.DaoImpl" init-method="init" destroy-method="destory"/>
方法二

实现InitializingBean, DisposableBean接口

public static DaoImpl implements Dao, InitializingBean, DisposableBean {
    public void save() {
        System.out.println("Dao save ... ")
    }
    public void init() throws Exception {
        System.out.println("Dao init ... ")
    }
    public void destroy() throws Exception {
        System.out.println("Dao destroy ... ")
    }
}
生命周期

初始化容器 1.创建对象(内存分配) 2.执行构造方法 3.执行属性注入( set操作) 4.执行bean初始化方法

使用bean 1.行业务操作

关闭/销毁容器 1.执行bean销毁方法

注:销毁的时机:容器关闭前触发bean的销毁 关闭容器方式: 手工关闭容器 ConfigurableApplicationContext接口close()

操作注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机 ConfigurableApplicationcontext接口registerShutdownHook ()操作

依赖注入

setter注入

引用类型

详情见博客 SSM01-Spring中的Bean

步骤如下 1.在bean中定义引用类型属性并提供可访问的set方法 2.配置中使用property标签ref属性注入引用类型对象

简单类型

步骤如下 1.在bean中定义引用类型属性并提供可访问的set方法 2.配置中使用property标签value属性注入简单类型数据

构造器注入

引用类型(仅做了解)

步骤如下 1.在bean中定义引用类型属性并提供可访问的构造方法 2.配置中使用constructor-arg标签ref属性注入引用类型对象

简单类型

步骤如下 1.在bean中定义引用类型属性并提供可访问的set方法 2.配置中使用property标签value属性注入简单类型数据 注意: 配置中使用constructor-arg标签type属性设置按形参类型注入 配置中使用constructor-arg标签index属性设置按形参位置注入

依赖注入方式的选择(总结自黑马程序员,侵删)

1.强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现 2.可选依赖使用setter注入进行,灵活性强 3.Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨 4.如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入 5.实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入 6.自己开发的模块推荐使用setter注入

自动装配(优先级低于setter注入与构造器注入)

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

自动装配方式

按类型(常用)(不能对简单类型装配)
<bean id="daoFactory" class="wang.dao.impl.DaoImpl" autowire="byType"/>

注意:需要set方法

注意:按类型(byType)时,同类型的应该只有一个bean,否则分不清。

按名称(set方法第一个字母改为小写的名称,即标椎的变量名)
<bean id="daoFactory" class="wang.dao.impl.DaoImpl" autowire="byName"/>

注意:因为变量名与byName耦合度高,不建议使用。

按构造方法

集合注入(主要学习格式)

Dao接口

package wang.dao;

public interface DataDao {
    public void save();
}

Dao实现

package wang.dao.impl;

import wang.dao.DataDao;

import java.util.*;

public class DataDaoImpl implements DataDao {

    private int[] array;

    private List<String> list;

    private Set<String> set;

    private Map<String,String> map;

    private Properties properties;




    public void setArray(int[] array) {
        this.array = array;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

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




    public void save() {
        System.out.println("book dao save ...");

        System.out.println("遍历数组:" + Arrays.toString(array));

        System.out.println("遍历List" + list);

        System.out.println("遍历Set" + set);

        System.out.println("遍历Map" + map);

        System.out.println("遍历Properties" + properties);
    }
}

配置文件:

<?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="dataDao" class="wang.dao.impl.DataDaoImpl">
        <!--数组注入-->
        <property name="array">
            <array>
                <value>100</value>
                <value>200</value>
                <value>300</value>
            </array>
        </property>
        <!--list集合注入-->
        <property name="list">
            <list>
                <value>java</value>
                <value>c++</value>
                <value>python</value>
                <value>php</value>
            </list>
        </property>
        <!--set集合注入-->
        <property name="set">
            <set>
                <value>java</value>
                <value>python</value>
                <value>java</value>
                <value>php</value>
            </set>
        </property>
        <!--map集合注入-->
        <property name="map">
            <map>
                <entry key="country" value="china"/>
                <entry key="province" value="shanxi"/>
                <entry key="city" value="xian"/>
            </map>
        </property>
        <!--Properties注入-->
        <property name="properties">
            <props>
                <prop key="country">china</prop>
                <prop key="province">shanxi</prop>
                <prop key="city">xian</prop>
            </props>
        </property>
    </bean>
</beans>

主函数:

package wang.dao;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App6 {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataDao dataDao = (DataDao) ctx.getBean("dataDao");
        dataDao.save();
    }
}

运行结果:

第三方资源注入

容器

两种加载容器的方式

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //推荐
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\ssm\\ssm\\springtest\\springtest\\src\\main\\resources\\applicationContext.xml"//绝对路径寻找

两种获取bean的方式

Dao dao = (DataDao) ctx.getBean("dao");
Dao dao = ctx.getBean("dao", Dao.class);  //多个同种类型报错

对比ApplicationContext和BeanFactory

BeanFactory是顶级接口的Bean是延迟加载

ApplicationContext是子接口(常用)也可以延迟加载,在bean中加入参数 lazy-init=“true” 即可

加载第三方Bean

加载Properties文件

步骤如下:

  1. 开启Context命名空间
  2. 使用context加载properties文件
  3. 使用属性占位符${}读取properties配置文件中的属性

样例代码如下:

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

    <!--步骤-->
    <!--1.开启命名空间-->
    <!--2.使用context加载properties文件-->
    <context:property-placeholder location="xxxx.properties"/>

    <!--3.使用属性占位符${}读取properties配置文件中的属性-->
    <bean class="xxxx">
        <property name="xxxx" value="${ 配置中的变量名称 }"/>
    </bean>
</beans>

注意:加载时可以关闭系统属性,因为系统属性的优先级高于

注意:多个配置文件用逗号隔开

注意:专业的写法加载所有配置文件如下

<!-- 加载properties文件标准格式 -->
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
<!-- 从类路径或jar包中搜索并加载properties文件
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>

总结(来自黑马程序员,侵删)

容器相关

bean相关

依赖注入相关

分类:

后端

标签:

后端

作者介绍

枉玖
V1

话不投机半句多