
枉玖
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文件
步骤如下:
-
开启Context命名空间 -
使用context加载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"
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相关

依赖注入相关

作者介绍

枉玖
话不投机半句多