Java的基础框架之Spring第一讲(IOC和DI)

Spring

spring

Spring是什么

Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>=90%

专业角度来说

简化开发,降低企业级开发的复杂性框架整合

高效整合其他技术,提高企业级应用开发与运行效率

  • 简化开发

    • IOC(反转控制)
    • AOP(面向切面编程)
    • DI(依赖注入)
      • 事务处理
  • 框架整合

    • MyBatis
    • MyBatis-plus
    • Struts
    • Struts2
    • Hibernate

初识Spring

Spring家族

官网:https://spring.io

Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能

spring全家桶

spring大家族

Spring发展史

spring发展史

Spring体系结构

Spring Framework系统架构图

Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基

Spring Framework系统架构图1

Spring Framework系统架构图2

Spring核心概述

目前代码存在的问题
  • 代码书写现状
    • 耦合度偏高
  • 解决方案
    • 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
概述
  • IOC(Inversion of Control)控制反转

    使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是“将new对象的权利交给Spring,我们从Spring中获取对象使用即可”

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

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

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

IOC

IOC和DI

IOC如何操作

  1. 导入Spring坐标

    <dependencies>
        <!--导入spring的坐标spring-context,对应版本是5.2.10.RELEASE-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
    </dependencies>
    
  2. 定义Spring管理的类(接口)

    BookDao接口和BookDaoImpl实现类

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

    BookService接口和BookServiceImpl实现类

    public interface BookService {
        public void save();
    }
    
    public class BookServiceImpl implements BookService {
        private BookDao bookDao = new BookDaoImpl();
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
  3. 创建Spring配置文件,配置对应类作为Spring管理的bean对象

    定义applicationContext.xml配置文件并配置BookServiceImpl

    <?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="bookService" class="com.itheima.service.impl.BookServiceImpl"></bean>
    
    </beans>
    
    注意

    bean定义时id属性在同一个上下文中(IOC容器中)不能重复

  4. 初始化IOC容器(Spring核心容器/Spring容器),通过容器获取Bean对象

    public class App {
        public static void main(String[] args) {
            //1.创建IoC容器对象,加载spring核心配置文件
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            //2 从IOC容器中获取Bean对象(BookService对象)
            BookService bookService= (BookService)ctx.getBean("bookService");
            //3 调用Bean对象(BookService对象)的方法
            bookService.save();
        }
    }
    

运行结果

IOC运行结果

DI如何操作

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

    public class BookServiceImpl implements BookService {
        private BookDao bookDao;  //【第一步】删除使用new的形式创建对象的代码
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
  2. 提供依赖对象对应的setter方法

    public class BookServiceImpl implements BookService {
        private BookDao bookDao;
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
        //【第二步】提供依赖对象对应的setter方法
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    }
    
  3. 配置service与dao之间的关系

    在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">
        <!--
    		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>
    

Bean的基础配置

Bean的基础配置

配置说明

配置说明

代码操作

见IOC和DI的applicationContext.xml配置

运行结果

见IOC和DI的运行结果

Bean别名配置

配置说明

别名配置说明

代码操作

别名代码演示

运行结果

别名运行结果

Bean作用范围配置

配置说明

作用范围配置说明

注意

scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中

代码操作

作用范围代码演示

运行结果

作用范围代码结果

在实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性

Bean的实例化

实例化Bean的三种方式

构造方法方式
BookDaoImpl实现类
public class BookDaoImpl implements BookDao {
    public BookDaoImpl() {
        System.out.println("book dao constructor is running ....");
    }
    public void save() {
        System.out.println("book dao save ...");
    }
}
applicationContext.xml配置
<!--方式一:构造方法实例化bean-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
AppForInstanceBook测试类
public class AppForInstanceBook {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

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

        bookDao.save();
    }
}
注意

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

静态工厂方式
OrderDao接口和OrderDaoImpl实现类
public interface OrderDao {
    public void save();
}
public class OrderDaoImpl implements OrderDao {
    public void save() {
        System.out.println("order dao save ...");
    }
}
OrderDaoFatory工厂类
//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");
        return new OrderDaoImpl();
    }
}
applicationContext.xml配置
<!--方式二:使用静态工厂实例化bean-->
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
AppForInstanceOrder测试类
public class AppForInstanceOrder {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");

        orderDao.save();
    }
}
实例工厂方式
UserDao接口和UserDaoImpl实现类
public interface UserDao {
    public void save();
}
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("user dao save ...");
    }
}
UserDaoFactory工厂类
//实例工厂创建对象
public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
applicationContext.xml配置
<!--方式三:使用实例工厂实例化bean-->
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>

<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
AppForInstanceUser测试类
public class AppForInstanceUser {
    public static void main(String[] args) {
        //        //创建实例工厂对象
        //        UserDaoFactory userDaoFactory = new UserDaoFactory();
        //        //通过实例工厂对象创建对象
        //        UserDao userDao = userDaoFactory.getUserDao();
        //        userDao.save();
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) ctx.getBean("userDao");
        userDao.save();
    }
}
实现FactoryBean<T>方式

实现FactoryBean<T>方式也是实例工厂的方式只不过更为方便

定义UserDaoFactoryBean实现FactoryBean<UserDao>

UserDaoFactoryBean中实例化什么类型的对象泛型就是该类型。

//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    public Class<?> getObjectType() {
        return UserDao.class;
    }
}
applicationContext.xml配置
<!--方式四:使用FactoryBean实例化bean-->
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>

Bean的生命周期

Bean生命周期控制第一种方式

提供生命周期控制方法
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    //表示bean初始化对应的操作
    public void init(){
        System.out.println("init...");
    }
    //表示bean销毁前对应的操作
    public void destory(){
        System.out.println("destory...");
    }
}
applicationContext.xml配置
<!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名-->
<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
测试类
public class AppForLifeCycle {
    public static void main( String[] args ) {
        //此处需要使用实现类类型,接口类型没有close方法
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        //关闭容器,执行销毁的方法
        ctx.close();
    }
}

Bean生命周期控制第二种方式

实现InitializingBean, DisposableBean接口
ublic class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        System.out.println("set .....");
        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");
    }
}

测试类代码同上

Bean销毁时机

  • 容器关闭前触发bean的销毁
  • 关闭容器方式
    • 手工关闭容器
      ConfigurableApplicationContext接口close()操作
    • 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
      ConfigurableApplicationContext接口registerShutdownHook()操作
public class AppForLifeCycle {
    public static void main( String[] args ) {
        //此处需要使用实现类类型,接口类型没有close方法
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
        ctx.registerShutdownHook();
        //关闭容器
        //ctx.close();
    }
}

依赖注入(DI配置)

依赖注入方式

依赖注入的两种方式
  • setter注入
    简单类型
    引用类型(很常用)
  • 构造器注入
    简单类型
    引用类型
setter方式注入
引用类型

引用类型set注入

简单类型

简单类型set注入

构造方式注入
引用类型

引用类型构造注入

简单类型

简单类型构造注入

参数适配

构造注入参数配置

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

依赖自动装配

自动装配类型
依赖自动装配

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

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
依赖自动装配特征
  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  2. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
  3. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
  4. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

集合注入

注入数组类型数据
<property name="array">
    <array>
        <value>100</value>
        <value>200</value>
        <value>300</value>
    </array>
</property>
注入List类型数据
<property name="list">
    <list>
        <value>aaa</value>
        <value>bbb</value>
        <value>ccc</value>
        <value>ddd</value>
    </list>
</property>
注入Set类型数据
<property name="set">
    <set>
        <value>aaa</value>
        <value>bbb</value>
        <value>ccc</value>
        <value>ccc</value>
    </set>
</property>
注入Map类型数据
<property name="map">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="henan"/>
        <entry key="city" value="xuchang"/>
    </map>
</property>
注入Properties类型数据
<property name="properties">
    <props>
        <prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">xuchang</prop>
    </props>
</property>
注意

property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

java白杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值