Spring 的IOC和bean详解

简介: Spring 的IOC和bean详解

*核心概念:

  • IOC(Inversion of Control)控制反转:
    目的:为了降低程序间的耦合度
    含义:把程序内主动new创造对象的过程交给外部程序去做,创建对象的过程中控制权由程序部转到了*外部*去实现。
    Spring对Ioc思想进行了实现:其提供了IOC容器来充当IOC思想的“外部”,IOC负责创建和管理对象,被创建和管理的对象在IOC中称为Bean
  • DI(Dependence Injection) 依赖注入:
    含义:在容器中建立bean之间的依赖关系。
  • 效果:使用对象是不仅可以直接从容器中取,还能获取到bean绑定的所有依赖关系。

1:IOC入门案例:

  1. pom.xml 配置文件中导入依赖
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>
  1. resourse文件夹中建立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,对应版本为5.2.10.RELEASE-->
        <!--2:配置bean-->
        <!--bean:配置bean-->
        <!--id:给bean起的别名-->
        <!--class:给bean定义类型-->
    <bean id="bookDao" class="com.ysj.dao.impl.BookDaoImpl">
    </bean>
    <bean id="bookService" class="com.ysj.service.impl.BookServiceImpl">
    </bean>
</beans>
  1. 在测试类中:
//3:加载配置文件,获取IOC容器对象
   ApplicationContext ext = new ClassPathXmlApplicationContext("applicationContext.xml");
            //4:获取bean
     //  BookDao bookDao = (BookDao) ext.getBean("bookDao");
     // bookDao.save();;
        BookService bookService = (BookService) ext.getBean("bookService");
        bookService.save();
  1. 入门案例中,此时在业务层实现中,仍存在new创建对象,耦合度相对来说仍然较高,接下来就到DI(Dependence Injection) 登场了。

2:DI(Dependence Injection)入门案例:

//7:删除new
private BookDao bookDao;
public void save() {
    System.out.println("book service save ...");
    bookDao.save();
}
//8:设置setter方法:容器创建对象会调用setter方法
public void setBookDao(BookDao bookDao) {
    this.bookDao = bookDao;
}

<bean id="bookService" class="com.ysj.service.impl.BookServiceImpl">
    <!-- 配置server与dao的关系(dao对象在server中创建,所以在server中配置)-->
    <!--  property:配置当前bean的属性,即对应类中的属性-->
    <!--  name:当前bean所对应的类中的具体属性-->
    <!--  ref:表示参照哪个bean进行配置-->
        <property name="bookDao" ref="bookDao"></property>
    </bean>

3:bean

3:bean的基础配置

3.1:name属性:给bean起别名,多个别名间用空格隔开

<bean id="bookDao" name="dao ss ss1"  class="com.ysj.dao.impl.BookDaoImpl">

3.2:bean默认是单例模式

<!--  scope:选择bean是否为单例模式
    prototype:多例
    singleton:单例-->
<bean id="bookDao" name="dao ss ss1" scope="prototype"
      class="com.ysj.dao.impl.BookDaoImpl">

3.3🏖bean默认是单例模式的原因

如果默认不是单例,那么创造的bean对象将会无穷无尽,增加了Spring的负担
  ##适合交给容器进行管理的bean
  1:表现层对象
  2:业务层对象
  3:数据层对象
  4:工具类对象
  ##不适合交给容器进行管理的bean
  封装实体类的域对象

3.4:常见报错

//原因:没有命名为‘ss2’的bean
//方法;检查bean容器别名和自己书写哪里不一致
NoSuchBeanDefinitionException: No bean named 'ss2' available

4:bean的实例化的三种方式

4.1:构造方法(常用)

##提供可访问的构造方法:无参(bean容器创建对象调用无参构造方法)
    ##如果没有无参构造方法将报‘BeanCreationException’,‘java.lang.NoSuchMethodException’异常

4.2:Spring报错处理方法

#从后往前看

4.3:静态工厂(了解)

//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");
        return new OrderDaoImpl();
    }
}
<!--    方式二:使用静态工厂实例化bean,记得配置工厂造对象的具体方法-->
<bean id="orderDao" class="com.ysj.factory.OrderDaoFactory" factory-method="getOrderDao"/>

4.4:实例工厂

4.4.1:实例工厂实例化(了解)
  • 第一个bean仅仅是为了配合使用,创造对象,除此之外无其他意义
  • factory-method:如果这样配置,方法名不固定,每次配置bean都要配置
<!--    方式三:使用实例工厂实例化bean-->
   <bean id="userFactory" class="com.ysj.factory.UserDaoFactory"/>
   <!--factory-bean:配置工厂类的bean-->
    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
4.4.2:FactoryBean(实用)
//FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法,bean中不必再配置factory-method,统一使用该方法创建对象
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }
    public Class<?> getObjectType() {
        return UserDao.class;
    }
    //true:创建对象是单例
    //false:创建对象非单例
    public boolean isSingleton() {
        return false;
    }
}
<!--方式四:使用FactoryBean实例化bean-->
<bean id="userDao" class="com.ysj.factory.UserDaoFactoryBean"/>

5:bean的生命周期

5.1: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("destroy...");
    }
}
<!--init-method:设置bean初始化生命周期回调函数-->
<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象-->
<bean id="bookDao" class="com.ysj.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

配置完后运行程序,会发现destroy方法没有运行,这时你大叫:“Why?”

其实是因为:我们这些程序运行在虚拟机上,当IOC容器加载完配置后,bean也初始化了,接着运行程序,

然而当程序运行完后,虚拟机退出了,俺类destroy并没有机会执行,呜呜呜呜~~

public static void main( String[] args ) {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    bookDao.save();
}

那么,如何让俺滴销毁方法执行呢?

有如下两个方法:

5.2:让销毁执行起来

注意把在加载IOC容器时定义ClassPathXmlApplicationContext对象

5.2.1:手动close(太暴力了,直接就停了)

用这个要注意使用的位置

public static void main( String[] args ) {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    bookDao.save();
    //关闭容器
    ctx.close();
}
5.2.3:注册关闭钩子函数

虚拟机会在退出之前调用此函数,进而关闭容器

public static void main( String[] args ) {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    bookDao.save();
    //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
    ctx.registerShutdownHook();
}

5.2:接口控制(了解)

按照Spring官方给的接口和规范进行配置

实现InitializingBean, DisposableBean接口

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    //在资源加载完后运行,但是在调用方法之前
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
    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");
    }
}

5.3:生命周期历程

  • 初始化容器
  1. 创建对象(内存分配,类似于new,在内存中分配了空间)
  2. 执行构造方法(对象创建完成)
  3. 执行属性注入(set操作)
  4. 执行bean的初始化方法
  • 使用bean
    执行业务层
  • 关闭/销毁容器
    执行bean的销毁方法

5.4:小记

所有bean在IOC容器加载完配置后就被初始化了

相关文章
|
1月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
6天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
6天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
58 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
7天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
7天前
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
1月前
|
XML Java 数据格式
Spring5入门到实战------5、IOC容器-Bean管理(三)
这篇文章深入探讨了Spring5框架中IOC容器的高级Bean管理,包括FactoryBean的使用、Bean作用域的设置、Bean生命周期的详细解释以及Bean后置处理器的实现和应用。
Spring5入门到实战------5、IOC容器-Bean管理(三)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
这篇文章是Spring5框架的入门教程,详细讲解了IOC容器中Bean的自动装配机制,包括手动装配、`byName`和`byType`两种自动装配方式,并通过XML配置文件和Java代码示例展示了如何在Spring中实现自动装配。
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
|
1月前
|
XML Java 数据格式
Spring5入门到实战------2、IOC容器底层原理
这篇文章深入探讨了Spring5框架中的IOC容器,包括IOC的概念、底层原理、以及BeanFactory接口和ApplicationContext接口的介绍。文章通过图解和实例代码,解释了IOC如何通过工厂模式和反射机制实现对象的创建和管理,以及如何降低代码耦合度,提高开发效率。
Spring5入门到实战------2、IOC容器底层原理
|
1月前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式
|
29天前
|
Java Spring