Spring-Day1 — IOC&DI

学什么

简化开发: Spring框架中提供了两个大的核心技术

  • IOC
  • AOP

核心概念

IOC & IOC容器 & Bean

  • IOC(Inversion of Control)控制反转
  • 不自己new对象,交给容器new – 解耦
  • IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象
  • 被创建或被管理的对象在IOC容器中统称为Bean

DI

  • (Dependency Injection)依赖注入
  • 建立容器中对象与对象之间的绑定关系
  • service运行需要依赖dao对象

案例

解耦BookDao

  1. pom.xml添加依赖

  2. 添加案例中需要的类

  3. 添加spring配置文件applicationContext.xml

      <?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">
    <!--1.导入spring的坐标spring-context-->
    <!--2.配置bean-->
    <!--bean标签标示配置bean
    id属性标示给bean起名字
    class属性表示给bean定义类型
    注意class不要写成接口类而是实现类,因为bean要找对象
    -->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/>

    </beans>
  4. 获取IOC容器、从容器中获取对象进行方法调用

       
    public class App {
    public static void main(String[] args) {
    //获取IOC容器
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    //getBean() 方法获取的 Bean 的标识符(id 或 name 属性的值),返回的是一个通用的 Object 类型,我们需要将其转换为 BookService 类型
    // BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    // bookDao.save();
    BookService bookService = (BookService) ctx.getBean("bookService");
    bookService.save();
    }
    }
  5. 运行程序测试

解耦BookService

  1. 去除BookServiceImpl中的new,为属性提供setter方法

    public class BookServiceImpl implements BookService {
    //删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

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

    //提供对应的set方法
    public void setBookDao(BookDao bookDao) {
    this.bookDao = bookDao;
    }
    }
  2. 修改配置完成注入

    <?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标签标示配置bean
    id属性标示给bean起名字
    class属性表示给bean定义类型-->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <!--配置server与dao的关系-->
    <!--property标签表示配置当前bean的属性
    name属性表示配置哪一个具体的属性/对象名称
    ref属性表示参照哪一个bean-->
    <property name="bookDao" ref="bookDao"/>
    </bean>
    </beans>
  3. 运行程序

关于bean

bean的基础配置

配置别名 name

<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>

配置范围(是否为单例) scode

<!--scope:为bean设置作用范围,可选值为单例singloton,非单例prototype-->
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>

bean的实例化

构造方法实例化 — 无参构造方法

在BookDaoImpl类中添加一个无参构造函数,并打印一句话,方便观察结果

静态工厂实例化 — 了解即可

实例工厂化 — 额额不太懂

  1. 准备一个Dao和DaoImpl类
  2. 创建一个工厂类OrderDaoFactory并提供一个普通方法
     public class UserDaoFactory {
    }
    }
  • 创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法
    public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    //替代UseDaoFactory的getUserDao方法
    public UserDao getObject() throws Exception {
    return new UserDaoImpl();
    }
    //返回所创建类的Class对象
    public Class<?> getObjectType() {
    return UserDao.class;
    }
    }
  1. 配置文件添加

    <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
  2. 编写AppForInstanceUser运行类,在类中通过工厂获取对象

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

bean的生命周期

bean对象从创建到销毁的整体过程

  • 初始化容器

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

    • 执行业务操作
  • 关闭/销毁容器

    • 执行bean销毁方法
  • 代码实现

    • 1.init&destory
    //添加两个接口`InitializingBean`, `DisposableBean`并实现接口中的两个方法`afterPropertiesSet`和`destroy`
    //这样就不用在配置文件里面配置`init-method`和`destroy-method`
    public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
    this.bookDao = bookDao;
    }
    public void save() {
    System.out.println("book service save ...");
    bookDao.save();
    }
    public void destroy() throws Exception {
    System.out.println("service destroy");
    }
    public void afterPropertiesSet() throws Exception {
    System.out.println("service init");
    }
    }
    • 2.close —执行destroy方法的内容
    //ApplicationContext中没有close方法,需要将ApplicationContext更换成ClassPathXmlApplicationContext
    ClassPathXmlApplicationContext ctx = new
    ClassPathXmlApplicationContext("applicationContext.xml");
    //运行程序,就能执行destroy方法的内容
    ctx.close();
    • 3.注册钩子关闭容器 — 执行destroy方法的内容

      ctx.registerShutdownHook();

DI

相关内容

setter注入

  • 简单类型
    <bean ...>
    <property name="" value=""/>
    </bean>
  • 引用类型
    <bean ...>
    <property name="" ref=""/>
    </bean>

构造器注入

  • 简单类型
    <bean ...>
    <constructor-arg name="" index="" type="" value=""/>
    </bean>
  • 引用类型
    <bean ...>
    <constructor-arg name="" index="" type="" ref=""/>
    </bean>

自动配置

  • 不用写配置文件了
  • 类型

按类型(常用)

<bean class="com.itheima.dao.impl.BookDaoImpl"/>
<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
</beans>

按名称 — 有多个相同类型的对象

<bean class="com.itheima.dao.impl.BookDaoImpl"/>
<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>
</beans>

按构造方法

集合注入

数组类型数据

<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>

注入List类型数据

<property name="list">
<list>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>chuanzhihui</value>
</list>
</property>

注入Set类型数据

<property name="set">
<set>
<value>itcast</value>
<value>itheima</value>
<value>boxuegu</value>
<value>boxuegu</value>
</set>
</property>

注入Map类型数据

<property name="map">
<map>
<entry key="country" value="china"/>
<entry key="province" value="henan"/>
<entry key="city" value="kaifeng"/>
</map>
</property>

注入Properties类型数据

<property name="properties">
<props>
<prop key="country">china</prop>
<prop key="province">henan</prop>
<prop key="city">kaifeng</prop>
</props>
</property>