Java 自定义Spring框架与核心功能详解

目录
  • Spring核心功能结构
  • 核心容器
    • spring-beans和spring-core模块
    • spring-context模块
    • spring-context-support模块
    • spring-context-indexer模块
    • spring-expression模块
    • AOP和设备支持
    • 数据访问与集成
    • Web组件
    • 通信报文
    • 集成测试
    • bean概述

在上一讲中,我们对Spring的基本使用进行了一个简单的回顾,接下来,我们就来看一下Spring核心功能结构。

Spring核心功能结构

Spring大约有20个模块,由1300多个不同的文件构成,而这些模块可以分为下面几部分:

  • 核心容器
  • AOP和设备支持
  • 数据访问与集成
  • Web组件
  • 通信报文
  • 集成测试
  • ······

下面这张图就是Spring框架的总体架构图。

接下来,我就带领着大家逐一看一下Spring里面的这些模块。

核心容器

核心容器由Beans、Core、Context和Expression(Spring Expression Language,SpEL)4个模块组成。

spring-beans和spring-core模块

spring-beans和spring-core模块是Spring框架的核心模块,包含了控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)。

这俩模块里面有一个核心接口叫BeanFactory,为什么说它是核心接口呢?因为Spring IoC里面有一个很重要的概念,那就是容器,而BeanFactory接口定义的就是容器共有的功能,很显然,BeanFactory就是容器对象顶层接口。下面,我们不妨再来重新认识一遍BeanFactory。

BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离。大家要知道,bean以及依赖的管理,我们都是在Spring的配置文件里面进行配置的,这样,是不是就能大大降低程序之间的耦合啊?

BeanFactory属于延时加载,也就是说在实例化容器对象后并不会自动实例化bean,只有当bean被使用时,BeanFactory才会对该bean进行实例化与依赖关系的装配。这句话什么意思呢?我们不妨先回到咱们的Maven工程(即spring_demo)中,然后再通过代码演示来理解一下这句话。现在我们创建Spring的容器对象就不再使用ApplicationContext接口了,而是来使用BeanFactory接口,如下所示。

package com.meimeixia.controller;

import com.meimeixia.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

/**
 * @author liayun
 * @create 2021-09-19 18:41
 */
public class UserController {
    public static void main(String[] args) throws Exception {
        // 1. 创建Spring的容器对象
        // ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        // 2. 从容器对象中获取UserService对象
        UserService userService = beanFactory.getBean("userService", UserService.class);
        // 3. 调用UserService对象的方法进行业务逻辑处理
        userService.add();
    }
}

以上UserController类的代码修改完毕之后,我们并不会看到延时加载的效果,为了看到延时加载的效果,我们还得分别在UserDaoImpl和UserServiceImpl这俩类里面提供一个无参构造方法,因为bean在实例化的时候,肯定是要调用其构造方法的。

  • UserDaoImpl类:
package com.meimeixia.dao.impl;

import com.meimeixia.dao.UserDao;

/**
* 数据访问层实现类
* @author liayun
* @create 2021-09-19 18:29
*/
public class UserDaoImpl implements UserDao {

    public UserDaoImpl() {
        System.out.println("userDao被创建了");
    }

    @Override
    public void add() {
        System.out.println("UserDao...");
    }

}
  • UserServiceImpl类:
package com.meimeixia.service.impl;

import com.meimeixia.dao.UserDao;
import com.meimeixia.service.UserService;

/**
* 业务逻辑层实现类
* @author liayun
* @create 2021-09-19 18:37
*/
public class UserServiceImpl implements UserService {

    // 因为业务逻辑层是要调用数据访问层中的功能的,所以在这儿我们得声明一个UserDao类型的变量
    private UserDao userDao; // 注意了,这儿我们并没有为该变量进行赋值,赋值的操作得交给Spring去做,只是这样做的前提是我们得为该变量提供一个setter方法

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserServiceImpl() {
        System.out.println("userService被创建了");
    }

    @Override
    public void add() {
        System.out.println("UserService...");
        userDao.add();
    }
}

为了方便大家看到延时加载的效果,于是我在UserController类的如下代码处打上了一个断点,然后我会以Debug的方式来运行UserController类的代码。

此时,程序肯定是要停留在断点处的,然后我们按下F6键让程序再往下运行一行代码,当你切换到控制台时,你会发现控制台并没有任何打印结果,如下图所示。

现在容器对象已经实例化完了,而且我们还为UserDaoImpl和UserServiceImpl这俩类提供了一个无参构造方法,照理来说,此时应该自动实例化bean的(就是自动创建UserDaoImpl和UserServiceImpl这俩类的对象),我们应该能够看到控制台中会打印相应结果的,因为创建UserDaoImpl和UserServiceImpl这俩类的对象,就必须得调用其无参构造。但是,控制台我们没有看到任何打印结果,这就说明在实例化容器对象后并不会自动实例化bean,原因正是BeanFactory属于延时加载。

那什么时候实例化bean呢?使用容器对象里面的getBean方法获取对应的对象时就会实例化bean了,当然了,并不是我们自个去实例化,而是Spring帮我们去实例化。所以,当你按下F6键让程序再往下运行一行代码之后,你就能够看到控制台中会打印相应结果了,如下图所示。

足以证明只有当bean被使用时,BeanFactory才会对该bean进行实例化与依赖关系的装配!OK,这里就给大家演示完了BeanFactory的延时加载。

spring-context模块

spring-context模块构架于核心模块(即spring-beans和spring-core这俩模块)之上,扩展了BeanFactory,为它添加了bean生命周期控制、框架事件体系及资源加载透明化等功能。此外,该模块还提供了许多企业级支持,如邮件访问、远程访问、任务调度等。

大家注意了,ApplicationContext是该模块的核心接口,它的超类是BeanFactory,也就是说它是BeanFactory的子接口。与BeanFactory不同,ApplicationContext实例化后会自动对所有的单实例bean进行实例化与依赖关系的装配,使之处于待用状态。

这又是啥子意思呢?还是回到咱们的Maven工程(即spring_demo)中,这里我依旧通过代码来给大家进行演示。现在我们创建Spring的容器对象还是使用ApplicationContext接口了,如下所示。

package com.meimeixia.controller;

import com.meimeixia.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

/**
 * @author liayun
 * @create 2021-09-19 18:41
 */
public class UserController {
    public static void main(String[] args) throws Exception {
        // 1. 创建Spring的容器对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        // 2. 从容器对象中获取UserService对象
        UserService userService = applicationContext.getBean("userService", UserService.class);
        // 3. 调用UserService对象的方法进行业务逻辑处理
        userService.add();
    }
}

依旧在UserController类的如下代码处打上了一个断点,然后以Debug的方式来运行UserController类的代码。

此时,程序肯定是要停留在断点处的,然后我们按下F6键让程序再往下运行一行代码,当你切换到控制台时,你会发现现在控制台有打印结果了,如下图所示。

这也就是说在实例化容器对象后就会自动实例化bean,我想大家也应该猜到原因了,就是与BeanFactory相反,ApplicationContext属于非延时加载。所以,这里大家一定要非常清楚BeanFactory和ApplicationContext的区别。

spring-context-support模块

spring-context-support模块是对Spring IoC容器及IoC子容器的扩展支持。

这里面涉及到了一个IoC子容器,想必大家都用过Spring MVC吧!它和Spring就牵扯到了一个父容器和子容器的关系,当然,这一块我们不做重点说明啊!

spring-context-indexer模块

spring-context-indexer模块是Spring的类管理组件和Classpath扫描组件。

想必大家都知道,如果我们在配置文件里面配置了一个组件扫描的话,那么它就会自动去扫描对应类路径下面的那些类有没有对应的注解。

spring-expression模块

spring-expression模块是统一表达式语言(EL)的扩展模块,可以查询、管理运行中的对象,同时也可以方便地调用对象方法,以及操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。EL的特性是基于Spring产品的需求而设计的,可以非常方便地同Spring IoC进行交互。

AOP和设备支持

用过Spring框架的话,那么你肯定用过AOP,相信你应该也是比较熟悉的,所以这里我就不再做过多赘述了。

数据访问与集成

其实,数据访问与集成这一模块说白了就是对Dao层进行封装的一个组件。

Web组件

对Web层进行封装的组件。

通信报文

从以上Spring框架的总体架构图中可以看到,Messaging代表的就是通信报文,这里我只是提一嘴。

集成测试

从以上Spring框架的总体架构图中可以看到,Test代表的就是集成测试,说白了就是Spring集成JUnit来进行单元测试。

当然了,Spring框架里面肯定还有一些其他模块,但我在这里不可能一一列出来,于是就只挑了如上几个模块来说了一下,其中要重点关注核心容器这一模块。

bean概述

接下来,我来为大家讲一讲Spring中的bean,因为bean对于Spring来说特别特别重要,所以我单独把它拿过来给大家讲一讲。

Spring就是面向bean的编程(简称BOP,Bean Oriented Programming),bean在Spring中处于核心地位。bean对于Spring的意义就像Object对于OOP的意义一样,如果Spring中没有了bean,那么也就没有Spring存在的意义了。Spring IoC容器通过配置文件或者注解的方式来管理bean对象之间的依赖关系。

接下来,我们来看一下什么是bean?

Spring中bean用于对一个类进行封装。如下面的配置:

<bean id="userDao" class="com.meimeixia.dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="com.meimeixia.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>

你会发现以上配置中用到了两个<bean>标签,而每一个<bean>标签就代表着一个bean。就拿第一个<bean>标签来说,id属性的值就是bean对象的名称,而class属性的值就是bean对象所属类的全限定类名。为什么要声明这俩属性呢?因为Spring底层在去创建bean对象时,是通过反射的方式根据全限定类名去创建该类的对象的。

为什么bean如此重要呢?这是因为:

  1. Spring将bean对象交由一个叫IoC的容器进行管理。也就是说IoC容器是以bean对象为单位来进行管理的。
  2. bean对象之间的依赖关系在配置文件中体现,并由Spring完成。

这里,我们简单地去聊了一下Spring中的bean,对于bean,大家应该还是要知道一点的。

到此这篇关于Java 自定义Spring框架与核心功能详解的文章就介绍到这了,更多相关Java 自定义Spring框架内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java 自定义Spring框架以及Spring框架的基本使用

    从现在开始,大家可以跟随着我的脚步来自定义一个属于自己的Spring框架.但是,在学习自定义Spring框架之前,我们得先来回顾一下Spring框架的基本使用.知晓了Spring框架的基本使用之后,我们将会在此基础上分析Spring的核心,即IoC,最后我们会对该核心进行一个模拟. 相信大家都使用过Spring框架,现在恐怕是无人不知Spring了吧!我相信你在实际项目开发中肯定用到过它,一般在实际项目中用到它的话,都会采用Java EE的三层架构,这三层架构是: 数据访问层,也即Dao层 业务

  • Java Spring框架简介与Spring IOC详解

    目录 Spring简介和配置 1.Spring概述 1.1 spring 是什么 1.2 Spring发展历程 1.3 Spring的优势 (理解) \1. 方便解耦,简化开发 \2. AOP 编程的支持 \3. 声明式事务的支持 \4. 方便程序的测试 \5. 方便集成各种优秀框架 \6. 降低 JavaEE API 的使用难度 \7. Java 源码是经典学习范例 1.4 Spring的体系结构(了解) 2.Spring IoC快速入门 2.1 IoC的概念和作用 2.2 Spring Io

  • Spring框架学习常用注解汇总

    目录 类注解 方法或属性上注解 参数注解 类注解 @component 标注类,泛指各种组件,类不属于各种分类的时候,用它做标注. @Service 标注类,声明该类为业务层组件,用于处理业务逻辑 @Repositor 标注类,声明该类为持久层的接口.使用后,在启动主程序类上需要添加@MapperScan("xxx.xxx.xxx.mapper")注解 @Mapper 标注类,用在持久层的接口上,注解使用后相当于@Reponsitory加@MapperScan注解,会自动进行配置加载

  • spring框架cacheAnnotation缓存注释声明解析

    目录 1.基于注释声明缓存 1.1@EnableCaching 1.2@Cacheable 1.2.1默认key生成规则 1.2.2声明自定义key 生成 1.2.3默认的cache resolution 1.2.4同步缓存 1.2.5 缓存的条件 1.2.6可用的Spel 评估上下文 1.基于注释声明缓存 声明缓存,Spring缓存抽象提供了一个java annotation集合. @Cacheable:触发缓存填充. @CacheEvict: 触发缓存删除. @CachePut: 不干扰方法

  • Java 自定义Spring框架与Spring IoC相关接口分析

    在本讲,我们来对Spring IoC功能相关的接口逐一进行分析,分析这些接口的原因就是为了我们自己定义Spring IoC功能提前做好准备. Spring IoC相关接口分析 BeanFactory接口解析 对于BeanFactory接口,我之前只是稍微提到过,并且将就着用了一下它.这里,我将会对BeanFactory接口进行一个具体讲解. Spring中bean的创建是典型的工厂模式,这一系列的bean工厂,即IoC容器,为开发者管理对象之间的依赖关系提供了很多便利和基础服务,在Spring中

  • 使用spring框架实现数据库事务处理方式

    目录 使用spring框架实现数据库事务处理 JDBC对数据库事务处理的支持 JDBC定义了五种事务隔离级别来解决这些并发导致的问题 在spring框架中调用一个数据库事务处理分三步走: spring 事务实现方式有哪些 在代码中调用 commit().rollback()等事务管理相关的方法 TransactionProxyFactoryBean 的声明式事务管理 注解 @Transactional 的声明式事务管理 Aspectj AOP 配置(注解)事务 使用spring框架实现数据库事务

  • Spring框架学习之Cache抽象详解

    目录 1.简介 cache和buffer 2.缓存抽象 3.spring缓存抽象与多进程 官方文档  8.0 Spring为不同缓存做了一层抽象,这里通过阅读文档以及源码会对使用以及原理做一些学习笔记. 1.简介 从3.1版开始,Spring Framework提供了对现有Spring应用程序透明地添加缓存的支持. 与事务支持类似,缓存抽象允许一致地使用各种缓存解决方案,而对代码的影响最小. 从Spring 4.1开始,通过JSR-107注释和更多自定义选项的支持,缓存抽象得到了显着改进. ca

  • Java 自定义Spring框架与核心功能详解

    目录 Spring核心功能结构 核心容器 spring-beans和spring-core模块 spring-context模块 spring-context-support模块 spring-context-indexer模块 spring-expression模块 AOP和设备支持 数据访问与集成 Web组件 通信报文 集成测试 bean概述 在上一讲中,我们对Spring的基本使用进行了一个简单的回顾,接下来,我们就来看一下Spring核心功能结构. Spring核心功能结构 Spring

  • Spring框架中@PostConstruct注解详解

    目录 初始化方式一:@PostConstruct注解 初始化方式二:实现InitializingBean接口 补充:@PostConstruct注释规则 总结 初始化方式一:@PostConstruct注解 假设类UserController有个成员变量UserService被@Autowired修饰,那么UserService的注入是在UserController的构造方法之后执行的. 如果想在UserController对象生成时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入的对

  • Spring框架学习之AOP详解

    一.概念 1.面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 2.通俗描述:不通过修改源代码方式,在主干功能里面添加新功能 二.底层原理:动态代理 有两种情况动态代理 2.1 有接口, JDK 动态代理 1.被代理的对象 public class UserDaoImpl implements UserDao { @Override public int add(int a, int b) {

  • Java进阶之高并发核心Selector详解

    一.Selector设计 笔者下载得是openjdk8的源码, 画出类图 比较清晰得看到,openjdk中Selector的实现是SelectorImpl,然后SelectorImpl又将职责委托给了具体的平台,比如图中框出的 linux2.6以后才有的EpollSelectorImpl Windows平台是WindowsSelectorImpl MacOSX平台是KQueueSelectorImpl 从名字也可以猜到,openjdk肯定在底层还是用epoll,kqueue,iocp这些技术来实

  • Java适配器模式应用之电源适配器功能详解

    本文实例讲述了Java适配器模式应用之电源适配器功能.分享给大家供大家参考,具体如下: 一.模式定义 存在两种适配器模式 1 对象适配器模式,在这种适配器模式中,适配器容纳一个它包裹的类对象的物理实体. 2 类适配器模式,在这种适配器模式中,适配器继承自已实现的类. 二.模式举例 1 模式分析 我们借用笔计本电源适配器来说明这一模式. 已经存在的交流电源 笔记本电脑 电源适配器 2 适配器模式的静态建模 3 代码举例 3.1 抽象电源建立 package com.demo.power; /**

  • Java NIO实战之聊天室功能详解

    本文实例讲述了Java NIO实战之聊天室功能.分享给大家供大家参考,具体如下: 在工作之余花了两个星期看完了<Java NIO>,总体来说这本书把NIO写的很详细,没有过多的废话,讲的都是重点,只是翻译的中文版看的确实吃力,英文水平太低也没办法,总算也坚持看完了.<Java NIO>这本书的重点在于第四章讲解的"选择器",要理解透还是要反复琢磨推敲:愚钝的我花了大概3天的时间才将NIO的选择器机制理解透并能较熟练的运用,于是便写了这个聊天室程序. 下面直接上代

  • java和Spring中观察者模式的应用详解

    目录 一.观察者模式基本概况 1.概念 2.作用 3.实现方式 二.java实现两种观察者模式 1.Observer接口和Observable类 2.EventObject和EventListener 三.Spring事件监听实战及原理 1.Spring如何使用EventObject和EventListener实现观察者? 2.先实战-要先会用 3.会原理-搞清楚为什么会这样 四.最后一张图总结 一.观察者模式基本概况 1.概念 观察者模式(Observer Design Pattern)也被称

  • java若依框架集成redis缓存详解

    目录 1.添加依赖 2.修改配置 3.增加配置 4.增加工具类 总结 1.添加依赖 ruoyi-common\pom.xml模块添加整合依赖 <!-- springboot整合redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dep

随机推荐