😧 Spring_day02 ✅(二)

简介: 😧 Spring_day02 ✅

2,核心容器


前面已经完成bean与依赖注入的相关知识学习,接下来我们主要学习的是IOC容器中的核心容器。


这里所说的核心容器,大家可以把它简单的理解为**ApplicationContext**,前面虽然已经用到过,但是并没有系统的学习,接下来咱们从以下几个问题入手来学习下容器的相关知识:


  • 如何创建容器?
  • 创建好容器后,如何从容器中获取bean对象?
  • 容器类的层次结构是什么?
  • BeanFactory是什么?


2.1 环境准备


在学习和解决上述问题之前,先来准备下案例环境:


  • 创建一个Maven项目
  • pom.xml添加Spring的依赖
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>


  • resources下添加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 id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>
  • 添加BookDao和BookDaoImpl类
public interface BookDao {
    public void save();
}
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}
  • 创建运行类App


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

最终创建好的项目结构如下:


1.png


2.2 容器


2.2.1 容器的创建方式


案例中创建ApplicationContext的方式为:


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

这种方式翻译为:类路径下的XML配置文件


除了上面这种方式,Spring还提供了另外一种创建方式为:


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

这种方式翻译为:文件系统下的XML配置文件


使用这种方式,运行,会出现如下错误:


1.png


从错误信息中能发现,这种方式是从项目路径下开始查找applicationContext.xml配置文件的,所以需要将其修改为:


ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");


说明:大家练习的时候,写自己的具体路径。


这种方式虽能实现,但是当项目的位置发生变化后,代码也需要跟着改,耦合度较高,不推荐使用。


2.2.2 Bean的三种获取方式


方式一,就是目前案例中获取的方式:


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


这种方式存在的问题是每次获取的时候都需要进行类型转换,有没有更简单的方式呢?


方式二:


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

这种方式可以解决类型强转问题,但是参数又多加了一个,相对来说没有简化多少。


方式三:


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


这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。


2.2.3 容器类层次结构


(1)在IDEA中双击shift,输入BeanFactory


1.png


(2)点击进入BeanFactory类,ctrl+h,就能查看到如下结构的层次关系


1.png


从图中可以看出,容器类也是从无到有根据需要一层层叠加上来的,大家重点理解下这种设计思想。


2.2.4 BeanFactory的使用


使用BeanFactory来创建IOC容器的具体实现方式为:


public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}

为了更好的看出BeanFactoryApplicationContext之间的区别,在BookDaoImpl添加如下构造函数:


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

如果不去获取bean对象,打印会发现:


  • BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建
  • ApplicationContext是立即加载,容器加载的时候就会创建bean对象
  • ApplicationContext要想成为延迟加载,只需要按照如下方式进行配置


 

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"  lazy-init="true"/>
</beans>

小结


这一节中所讲的知识点包括:


  • 容器创建的两种方式
  • ClassPathXmlApplicationContext[掌握]
  • FileSystemXmlApplicationContext[知道即可]
  • 获取Bean的三种方式
  • getBean("名称"):需要类型转换
  • getBean("名称",类型.class):多了一个参数
  • getBean(类型.class):容器中不能有多个该类的bean对象


上述三种方式,各有各的优缺点,用哪个都可以。


  • 容器类层次结构
  • 只需要知晓容器的最上级的父接口为 BeanFactory即可
  • BeanFactory
  • 使用BeanFactory创建的容器是延迟加载
  • 使用ApplicationContext创建的容器是立即加载
  • 具体BeanFactory如何创建只需要了解即可。


2.2 核心容器总结


这节中没有新的知识点,只是对前面知识的一个大总结,共包含如下内容:


2.2.1 容器相关


  • BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
  • ApplicationContext接口常用初始化类
  • ClassPathXmlApplicationContext(常用)
  • FileSystemXmlApplicationContext


2.2.2 bean相关


1.png


其实整个配置中最常用的就两个属性id和class。


把scope、init-method、destroy-method框起来的原因是,后面注解在讲解的时候还会用到,所以大家对这三个属性关注下。


2.2.3 依赖注入相关


1.png


3,IOC/DI注解开发


Spring的IOC/DI对应的配置开发就已经讲解完成,但是使用起来相对来说还是比较复杂的,复杂的地方在配置文件。


前面咱们聊Spring的时候说过,Spring可以简化代码的开发,到现在并没有体会到。


所以Spring到底是如何简化代码开发的呢?


要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:


  • 2.0版开始支持注解
  • 2.5版注解功能趋于完善
  • 3.0版支持纯注解开发


关于注解开发,我们会讲解两块内容注解开发定义bean纯注解开发


注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。


3.1 环境准备


在学习注解开发之前,先来准备下案例环境:


  • 创建一个Maven项目
  • pom.xml添加Spring的依赖


 

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>
  • resources下添加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 id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>
  • 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类
public interface BookDao {
    public void save();
}
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}
public interface BookService {
    public void save();
}
public class BookServiceImpl implements BookService {
    public void save() {
        System.out.println("book service save ...");
    }
}

创建运行类App

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

最终创建好的项目结构如下:


1.png


3.2 注解开发定义bean


在上述环境的基础上,我们来学一学Spring是如何通过注解实现bean的定义开发?


步骤1:删除原XML配置


将配置文件中的标签删除掉

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

步骤2:Dao上添加注解


在BookDaoImpl类上添加@Component注解


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


注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。


XML与注解配置的对应关系:


1.png


步骤3:配置Spring的注解包扫描


为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描


 

<?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">
    <context:component-scan base-package="com.itheima"/>
</beans>

说明:


component-scan


  • component:组件,Spring将管理的bean视作自己的一个组件
  • scan:扫描


base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。


  • 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
  • 包路径越少[如:com.itheima],扫描的范围越大速度越慢
  • 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。


步骤4:运行程序


运行App类查看打印结果


1.png


步骤5:Service上添加注解


在BookServiceImpl类上也添加@Component交给Spring框架管理

@Component
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

步骤6:运行程序


在App类中,从IOC容器中获取BookServiceImpl对应的bean对象,打印

public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        System.out.println(bookDao);
        //按类型获取bean
        BookService bookService = ctx.getBean(BookService.class);
        System.out.println(bookService);
    }
}

打印观察结果,两个bean对象都已经打印到控制台


1.png


说明:


  • BookServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
  • @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如


BookService bookService = (BookService)ctx.getBean("bookServiceImpl");
System.out.println(bookService);


对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository


通过查看源码会发现:


1.png


这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?


方便我们后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。


知识点1:@Component等

名称

@Component/@Controller/@Service/@Repository

类型

类注解

位置

类定义上方

作用

设置该类为spring管理的bean

属性

value(默认):定义bean的id



目录
相关文章
|
XML Java 程序员
😧 Spring_day03(一)
😧 Spring_day03
88 1
|
XML 前端开发 Java
😧 SpringBoot(二)
😧 SpringBoot
70 1
|
Java 关系型数据库 MySQL
😧 SpringBoot(三)
😧 SpringBoot
84 1
|
druid Java 关系型数据库
😧 SpringBoot(四)
😧 SpringBoot
87 0
|
开发框架 Java 数据库连接
😧 Spring_day01 ✅(一)
😧 Spring_day01 ✅
93 0
|
Java Maven Spring
😧 Spring_day01 ✅(三)
😧 Spring_day01 ✅
104 0
|
druid Java 数据库连接
😧 Spring_day02 ✅(五)
😧 Spring_day02 ✅
94 0
|
XML Java 关系型数据库
😧 Spring_day02 ✅(四)
😧 Spring_day02 ✅
52 0
|
Java 数据库连接 数据库
😧 Spring_day03(五)
😧 Spring_day03
53 0
|
监控 Java 测试技术
😧 Spring_day03(四)
😧 Spring_day03
71 0