• 【JAVA】Spring(上)—— bean的实例化与注入


    目录

    【Spring】

    【Spring Framework系统框架4.x】

    【IoC】—— Inversion of Control 控制反转

    【Spring技术对IoC思想进行了实现】

    【DI】—— Dependency Injection 依赖注入

    【目标】—— 充分解耦

    【IoC使用】

    【DI使用】

    【bean】

    【基础配置】

    【别名配置】

    【作用范围配置】​编辑

    【bean的三种实例化方式】

    【第一种】—— 构造方法

    【第二种】—— 静态工厂

    【第三种】—— 实例工厂

    【bean生命周期】

    【bean生命周期控制】

    【bean销毁时机】

    【依赖注入方式(两种)】

    【setter注入】

    【构造器注入】

    【可优化构造器注入】—— 参数配置(依然有弊端)

    【依赖注入方式选择】

    【依赖自动装配】

    【集合注入】

    【案例】—— 数据源对象管理

    【加载properties文件】

    【使用】

    【其他功能使用】


    【Spring】

    【官网】

    Spring | Home

    【Spring Framework系统框架4.x】

    【IoC】—— Inversion of Control 控制反转

    【概述】

    使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转

    【Spring技术对IoC思想进行了实现】

    • Spring提供了一个容器,称为IoC容器,用来充当IoC思想中的“外部
    • IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean

    【DI】—— Dependency Injection 依赖注入

    【概述】

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

    【目标】—— 充分解耦

    【方法】

    • 使用IoC容器管理beanIoC)
    • 在IoC容器内将有依赖关系的bean进行关系绑定(DI

    【IoC使用】

    1、导入Spring坐标

    1. <dependency>
    2. <groupId>org.springframeworkgroupId>
    3. <artifactId>spring-contextartifactId>
    4. <version>5.2.10.RELEASEversion>
    5. dependency>

    2、定义Spring管理的类(接口&实现类)

    2.1、Dao

    1. public interface BookDao {
    2. void save();
    3. }
    1. public class BookDaoImpl implements BookDao {
    2. public void save() {
    3. System.out.println("book dao save...");
    4. }
    5. }

    2.2、Service

    1. public interface BookService {
    2. void save();
    3. }
    1. public class BookServiceImpl implements BookService {
    2. private BookDao bookDao = new BookDaoImpl();
    3. public void save() {
    4. System.out.println("book service save...");
    5. bookDao.save();
    6. }
    7. }

    3、配置Spring配置文件(applicationContext.xml),配置对应类作为Spring管理的bean

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    6. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/>
    7. beans>

    【注意】

    bean定义是id属性在同一上下文中不能重复

    4、初始化IoC容器(Spring容器),通过容器获取bean

    1. public static void main(String[] args) {
    2. //获取IoC容器
    3. ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    4. //获取bean
    5. BookService bookService = (BookService) ctx.getBean("bookService");
    6. bookService.save();
    7. }

    【DI使用】

    1、删除使用new的形式创建对象的代码

    1. public class BookServiceImpl implements BookService {
    2. private BookDao bookDao;
    3. public void save() {
    4. System.out.println("book service save...");
    5. bookDao.save();
    6. }
    7. }

    2、提供依赖对象对应的setter方法

    1. public class BookServiceImpl implements BookService {
    2. private BookDao bookDao;
    3. public void save() {
    4. System.out.println("book service save...");
    5. bookDao.save();
    6. }
    7. //提供对应的set方法
    8. public void setBookDao(BookDao bookDao) {
    9. this.bookDao = bookDao;
    10. }
    11. }

    3、配置service与dao之间的关系

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    2. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    3. <property name="bookDao" ref="bookDao"/>
    4. bean>

    【bean】

    【基础配置】

    【别名配置】

    【注意】  

    获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常

    NoSuchBeanDefinitionException: No bean named 'bookServiceImpl' available

    【作用范围配置】

    【注意】

    1、适合交给容器进行管理的bean

    • 表现层对象
    • 业务层对象
    • 数据层对象
    • 工具对象

    2、不适合交给容器进行管理的bean

    • 封装实体的域对象

    【bean的三种实例化方式】

    【第一种】—— 构造方法

    1、提供可访问的构造对象

    1. public class BookDaoImpl implements BookDao {
    2. public BookDaoImpl() {
    3. }
    4. public void save() {
    5. System.out.println("book dao save...");
    6. }
    7. }

    2、配置

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

    【注意】

    无参构造方法如果不存在,将抛出异常BeanCreationException

    【第二种】—— 静态工厂

    1、提供静态工厂

    1. public class OrderDaoFactory {
    2. public static OrderDao getOrderDao(){
    3. return new OrderDaoImpl();
    4. }
    5. }

    2、配置

    1. <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>

    【第三种】—— 实例工厂

    1、提供实例工厂

    1. public class UserDaoFactory {
    2. public UserDao getUserDao() {
    3. return new UserDaoImpl();
    4. }
    5. }

    2、配置

    1. <bean id="userDaoFactory" class="com.itheima.factory.UserDaoFactory"/>
    2. <bean id="userDao" factory-method="getUserDao" factory-bean="userDaoFactory"/>

    【优化】

    1、提供FactoryBean

    1. public class UserDaoFactoryBean implements FactoryBean {
    2. //代替原始实例工厂中创建对象的方法
    3. //得到bean实例
    4. @Override
    5. public UserDao getObject() throws Exception {
    6. return new UserDaoImpl();
    7. }
    8. //得到bean类型
    9. @Override
    10. public Class getObjectType() {
    11. return UserDao.class;
    12. }
    13. //设置是否单例,true:单例,false:非单例,默认单例
    14. @Override
    15. public boolean isSingleton() {
    16. return true;
    17. }
    18. }

    2、配置

    1. <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>

    bean生命周期

    【概述】

    • 生命周期:从创建到消亡的完整过程
    • bean生命周期:bean从创建到销毁的整体过程
    • bean生命周期控制:在bean创建后到销毁前做一些事情

    【流程】

    • 初始化容器
    1. 创建对象(内存分配)
    2. 执行构造方法
    3. 执行属性注入(set操作)
    4. 执行bean初始化方法
    • 使用bean
    1. 执行业务操作
    • 关闭/销毁容器
    1. 执行bean销毁方法

    【bean生命周期控制】

    【配置生命周期控制方法】

    1、提供生命周期控制方法

    1. public class BookDaoImpl implements BookDao {
    2. public void save() {
    3. System.out.println("book dao save...");
    4. }
    5. //表示bean初始化时对应的操作
    6. public void init() {
    7. System.out.println("init...");
    8. }
    9. //表示bean销毁前时对应的操作
    10. public void destroy() {
    11. System.out.println("destroy...");
    12. }
    13. }

    2、配置

        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>

    3、主程序调用

    1. public class AppForLiftCycle {
    2. public static void main(String[] args) {
    3. ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContextLift.xml");
    4. //注册关闭容器钩子,可放在任意位置
    5. ctx.registerShutdownHook();
    6. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    7. bookDao.save();
    8. //暴力关闭容器,只能放在最后
    9. //ctx.close();
    10. }
    11. }

    【接口控制生命周期控制方法】

    1、实现InitializingBean, DisposableBean接口

    1. public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    2. private BookDaoImpl bookDao;
    3. @Override
    4. public void save() {
    5. System.out.println("book service save...");
    6. }
    7. public void setBookDao(BookDaoImpl bookDao) {
    8. this.bookDao = bookDao;
    9. }
    10. @Override
    11. public void destroy() throws Exception {
    12. System.out.println("service destroy");
    13. }
    14. @Override
    15. public void afterPropertiesSet() throws Exception {
    16. System.out.println("service init");
    17. }
    18. }

    2、配置

    1. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    2. <property name="bookDao" ref="bookDao"/>
    3. bean>

     3、主程序调用

    1. public class AppForLiftCycle {
    2. public static void main(String[] args) {
    3. ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContextLift.xml");
    4. //注册关闭容器钩子,可放在任意位置
    5. ctx.registerShutdownHook();
    6. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    7. bookDao.save();
    8. //暴力关闭容器,只能放在最后
    9. //ctx.close();
    10. }
    11. }

    【bean销毁时机】

    容器关闭前触发bean的销毁

    • 关闭方式:(两种)
    1. 手工关闭容器:ConfigurableApplicationContext接口close()操作
    2. 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机:ConfigurableApplicationContext接口registerShutdownHook()操作

    【依赖注入方式(两种)】

    【setter注入】

    • 引用类型

    【使用】

    1、在bean中定义引用类型属性并提供可访问的set方法

    1. public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    2. private BookDaoImpl bookDao;
    3. public void setBookDao(BookDaoImpl bookDao) {
    4. this.bookDao = bookDao;
    5. }
    6. }

    2、配置中使用property标签ref属性注入引用类型对象

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
    2. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    3. <property name="bookDao" ref="bookDao"/>
    4. bean>
    • 简单类型

    【使用】

    1、在bean中定义引用类型属性并提供可访问的set方法

    1. public class BookDaoImpl implements BookDao {
    2. private int connectionNum;
    3. private String databaseNum;
    4. public void setConnectionNum(int connectionNum) {
    5. this.connectionNum = connectionNum;
    6. }
    7. public void setDatabaseNum(String databaseNum) {
    8. this.databaseNum = databaseNum;
    9. }
    10. public void save() {
    11. System.out.println("book service save..." + databaseNum + "," + connectionNum);
    12. }
    13. }

    2、配置中使用property标签value属性注入简单类型数据

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    2. <property name="databaseNum" value="mysql"/>
    3. <property name="connectionNum" value="10"/>
    4. bean>

    【构造器注入】

    • 引用类型

    【使用】

    1、在bean中定义引用类型属性并提供可访问的构造方法

    1. public class BookServiceImpl implements BookService {
    2. private BookDao bookDao;
    3. private UserDao userDao;
    4. public BookServiceImpl(BookDaoImpl bookDao, UserDaoImpl userDao) {
    5. this.bookDao = bookDao;
    6. this.userDao = userDao;
    7. }
    8. public void save() {
    9. System.out.println("book service save...");
    10. bookDao.save();
    11. userDao.save();
    12. }
    13. }

    2、配置中使用constructor-arg标签ref属性注入引用类型对象

    1. <bean id="bookDao" class="com.itheima2.dao.impl.BookDaoImpl"/>
    2. <bean id="userDao" class="com.itheima2.dao.impl.UserDaoImpl"/>
    3. <bean id="bookService" class="com.itheima2.service.impl.BookServiceImpl">
    4. <constructor-arg name="bookDao" ref="bookDao"/>
    5. <constructor-arg name="userDao" ref="userDao"/>
    6. bean>
    • 简单类型

    【使用】

    1、在bean中定义引用类型属性并提供可访问的set方法

    1. public class BookDaoImpl implements BookDao {
    2. private int connectionNum;
    3. private String databaseNum;
    4. public BookDaoImpl(int connectionNum, String databaseNum) {
    5. this.connectionNum = connectionNum;
    6. this.databaseNum = databaseNum;
    7. }
    8. public void save() {
    9. System.out.println("book dao save..."+databaseNum+connectionNum );
    10. }
    11. }

    2、配置中使用constructor-arg标签value属性注入简单类型数据

    1. <bean id="bookDao" class="com.itheima2.dao.impl.BookDaoImpl">
    2. <constructor-arg name="databaseNum" value="mysql"/>
    3. <constructor-arg name="connectionNum" value="10"/>
    4. bean>

    【注意】

    name与形参名称一致 

    【可优化构造器注入】—— 参数配置(依然有弊端)

    1、配置中使用constructor-arg标签type属性设置按形参类型注入

    1. <bean id="bookDao" class="com.itheima2.dao.impl.BookDaoImpl">
    2. <constructor-arg type="int" value="10"/>
    3. <constructor-arg type="java.lang.String" value="mysql"/>
    4. bean>

    2、配置中使用constructor-arg标签index属性设置按形参位置注入

    1. <bean id="bookDao" class="com.itheima2.dao.impl.BookDaoImpl">
    2. <constructor-arg index="1" value="mysql"/>
    3. <constructor-arg index="0" value="10"/>
    4. bean>

    【依赖注入方式选择】

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

    【依赖自动装配】

    【概述】

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

    【自动装配方式】

    • 按类型(byType)
    • 按名称(byName)

    【使用】

    配置中使用bean标签autowire属性设置自动装配的类型

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    2. <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>

    【注意】

    1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作
    2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
    3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
    4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

    【集合注入】

    【种类】

    • 注入数组
    • 注入List
    • 注入Set
    • 注入Map
    • 注入Properties

    例:

    1. <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    2. <property name="array">
    3. <array>
    4. <value>100value>
    5. <value>200value>
    6. <value>300value>
    7. array>
    8. property>
    9. <property name="list">
    10. <list>
    11. <value>abcvalue>
    12. <value>defvalue>
    13. <value>ghivalue>
    14. <value>ghivalue>
    15. list>
    16. property>
    17. <property name="set">
    18. <set>
    19. <value>abcvalue>
    20. <value>defvalue>
    21. <value>ghivalue>
    22. <value>ghivalue>
    23. set>
    24. property>
    25. <property name="map">
    26. <map>
    27. <entry key="country" value="china"/>
    28. <entry key="province" value="shanxi"/>
    29. <entry key="city" value="xian"/>
    30. map>
    31. property>
    32. <property name="properties">
    33. <props>
    34. <prop key="country">chinaprop>
    35. <prop key="province">shanxiprop>
    36. <prop key="city">xianprop>
    37. props>
    38. property>
    39. bean>

    【案例】—— 数据源对象管理

    【实现】

    1、导入druid坐标

    1. <dependency>
    2. <groupId>com.alibabagroupId>
    3. <artifactId>druidartifactId>
    4. <version>1.1.16version>
    5. dependency>

    2、配置数据源对象作为spring管理的bean

    1. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    2. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    3. <property name="url" value="jdbc:mysql://127.0.0.1:3306/spring_db"/>
    4. <property name="username" value="root"/>
    5. <property name="password" value="root"/>
    6. bean>

    【加载properties文件】

    【使用】

    1、开启命名空间

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xmlns:context="http://www.springframework.org/schema/context"
    5. xsi:schemaLocation="
    6. http://www.springframework.org/schema/beans
    7. http://www.springframework.org/schema/beans/spring-beans.xsd
    8. http://www.springframework.org/schema/context
    9. http://www.springframework.org/schema/context/spring-context.xsd">
    10. beans>

    2、使用context命名空间,加载指定properties文件

    <context:property-placeholder location="jdbc.properties"/>

    3、使用${ }占位符读取加载的属性值

    例:

    1. <property name="driverClassName" value="${jdbc.diver}"/>
    2. <property name="username" value="${jdbc.username}"/>

    4、在properties文件中写出属性值的内容

    例:

    1. jdbc.diver = com.mysql.jdbc.Driver
    2. jdbc.username = root

    【其他功能使用】

    • 不加载系统属性
    <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
    • 加载多个properties
    <context:property-placeholder location="jdbc.properties,msg.properties"/>
    
    • 加载所有properties
    <context:property-placeholder location="*.properties"/>
    • 加载properties文件标准格式(重点)
    <context:property-placeholder location="classpath:*.properties"/>
    • 从类路径或jar包中搜索并加载properties文件
    <context:property-placeholder location="classpath*:*.properties"/>

    【容器】

    【创建容器】

    【两种方式】

    第一种:类路径加载配置文件

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

    第二种:文件路径加载配置文件(绝对路径)

    ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml");

    加载多个配置文件

    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean1.xml", "bean2.xml");

    【获取bean】

    【三种方式】

    方式一:使用bean名称获取

    BookDao bookDao = (BookDao) ctx.getBean("bookDao");

    方式二:使用bean名称获取并指定类型

    BookDao bookDao = ctx.getBean("bookDao", BookDao.class);

    方式三:使用bean类型获取

    BookDao bookDao = ctx.getBean(BookDao.class);
  • 相关阅读:
    MVC模式和三层架构开发思想的概述
    02.1、数据操作
    Redhat 恢复模式重置root用户密码
    【Java】有 A、B、C 三个线程,如何保证三个线程同时执行?在并发情况下,如何保证三个线程依次执行?如何保证三个线程有序交错执行?
    zabbix 自动发现
    【学习教程】MCM箱模型建模方法及大气O3来源解析实践技术应用
    宏观经济学复习
    [爬虫]5.数据解析及应用 之 xpath 【爬取某城市所有景点的所有评论】
    python协议解析
    LightDB中的存储过程(三)
  • 原文地址:https://blog.csdn.net/huihu__/article/details/126506004