一:Spring框架功能整体介绍



二:根据Spring架构图可知,包含以上的模块儿。下面逐个模块儿进行解释。

1:IOC 和 DI(Inversion of Control I DependencyInjection ( IoC/DI ) 最最最最核心的功能是 :通过多级缓存解决循环依赖问题。

2:Spring Core Container:

模块作用:Core 和 Beans 模块是框架的基础部分,提供 IoC (转控制)和依赖注入特性,Spring Core也是核心层,拥有着BeanFactory这个强大的工厂,是所有bean的管理器。负责发现、创建并处理bean之间的关系的一个工具包。提供了对工厂模式的经典实现,实现对程序单例模式的需要。并真 正地允许你从程序逻辑中分离出依赖关系和配置。core主要包含 Spring 框架基本的核心工具类, Spring 的其他组件都要用到这个包 里的类, Core模块是其他组件的基本核心。

Spring Beans(BeanFactory):其中最重要的两个接口是:BeanFactory和BeanDefinition。BeanFacoty:是springIOC核心工厂接口,根据对象的依赖关系进行创建对象。ApplicationContext就是其中的一个具体实现。要定义一个工厂必须满足三个条件1,需要持有各种bean的定义2,需要持有Bean之间的依赖关系3,需要读取xml配置文件的工具。说白了。BeanFactory就是负责对bean的创建。

3:Context

context负责处理BeanFactory,主要的接口是ApplicationContext。ApplicationContext接口继承了ListableBeanFactory和HierarchicalBeanFactory接口他们都继承了BeanFactory接口。ApplicationContext模构建于 Core 和 Beans 模块基础之上,提供了一种类似JNDI 注册器的框 架式的对象访问方法。 Context 模块继承了 Beans 的特性,为 Spring 核心提供了大量扩展,添加了对国际化(例如资源绑定)、事件传播、资源加载和对 Context 的透明创 建的支持。 Context 模块同时也支持 J2EE 的一些特 性, ApplicationContext 接口是 Context 模块的关键。

4:ApplicationContext和BeanFactory的主要区别

·1,BeanFactory在启动的时候不会去实例化Bean,只有从容器中拿Bean的时候才会去实例化;BeanFactory是懒加载,BeanFactory需要手动注册。优点是:应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;

2,ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化; 优点是1. 所有的Bean在启动的时候都加载,系统运行的速度快; 2. 在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题 3. 建议web应用,在启动的时候就把所有的Bean都加载了。(把费时的操作放到系统启动中完成)

5:Expression Language(表达式语言)

模块提供了强大的表达式语言,用于在运行时查询和操纵对象。 它是 JSP 2.1 规范中定义的 unifedexpression language 的扩展。 该语言支持设直/获取属 性的值,属性的分配,方法的调用,访问数组上下文( accessiong the context of arrays )、 容器和索引器、逻辑和算术运算符、命名变量。以及从Spring的 IoC 容器中根据名称检 索对象。 它也支持 list 投影、选择和一般的 list 聚合

三:Spring Data Access/Integration

1:jdbc

模块提供了一个 JDBC 抽象层,它可以消除冗长的 JDBC 编码和解析数据库厂 商特有的错误代码。这个模块包含了 Spring 对 JDBC 数据访问进行封装的所有类

2:ORM 模块为流行的对象-关系映射 API

如 JPA、 JDO、 Hibernate、 iBatis 等,提供了 一个交互层。 利用 ORM 封装包,可以混合使用所。有 Spring 提供的特性进行 O/R 映射, 如前边提到的简单声 明性事务管理。OXM 模块提供了一个对 ObjecνXML 映射实现的抽象层。Object/XML 映射实现包括 JAXB、 Castor、 XMLBeans、 JiBX 和 XStrearn

3:JMS ( Java Messaging Service )

模块主要包含了 一些制造和消 费消息的特性。

4:Transaction

支持编程和声明性的事务管理,这些事务类必须实现特定的接口,并 且对所有的 POJO 都适用

5:Spring Web

Web 模块:提供了基础的面向 Web 的集成特性c 例如,多文件上传、使用 servlet listeners 初始化。IoC 容器以及一个面向 Web 的应用上下文。 它还包含 Spring 远程支持中 Web 的相关部分。

6:Spring Aop

AOP是切面编程。Aop Aspects 模块提供了对 AspectJ 的集成支持 。Instrumentation 模块提供了 class instrumentation 支持和 classloader 实现,使得可以在特定的应用服务器上使用。

7:Test

Test 模块支持使用 JUnit 和 TestNG 对 Spring 组件进行测试


四:Spring 容器继承图


一:什么是IOC?以及IOC的作用

上文提到IOC最最最核心的功能是通过多级缓存解决依赖注入问题。IOC被称为控制反转/依赖注入。什么是控制反转?我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversion Principle)

1,什么是依赖倒置原则?

假设我们是一名卖货的商家,比如我们进货,需要从进货市场进货,进货市场要从生产家下订单。这里就出现了一个依赖的关系,商家依赖进货市场,进货市场依赖生产厂家。依赖关系如下图所示


2,敲黑板,划重点.IOC容器的最最最最核心思想........................

ioc的思想最核心的地方在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度.如果用生活中的例子演示,就好比:如果在没有IOC容器之前的概念是,比如你要找一个女朋友,那么可能你需要具备以下几个特征:

生活中的依赖关系:有钱、长得帅、活儿好、会做饭、会收拾家务、温柔。


通过IOC解决依赖关系

以上可知,如果我们要找个女朋友,可能需要依赖很多外在因素。相对困难,复杂,成功率不高。更影响心情。但是有了IOC以后这个问题就可以非常容易的解决。如以下关系图所示。


通过上图可知,资源的拥有者是洗浴中心,但是洗浴中心本身并不使用资源,资源的使用者,不需要依赖那么的外在关系,只要有钱,告诉洗浴中心,我想要找某一个小姐姐,那么洗浴中心,就会给你安排你挑选的那个小姐姐为你服务,比如做一些羞羞的事情。。。。

IOC容器解决了,耦合度的问题,把资源交给第三方来管理(IOC容器)但本身并不使用资源。避免了依赖关系。从而解决耦合度的问题。

IOC源于生活,高于生活。


二:Spring IOC 容器底层注解使用

1,依赖注入和分为XML和注解两种方式,这里主要重点介绍注解的方式,目前SpringBoot 和SpringCloud是趋势,所以以后开发过程中强烈推荐用注解,不仅简洁,方便,又可以提高开发效率。不容易出错,节省了开发时间和改错时间。

2,通过XML的方式配置IOC这里不做介绍,ClassPathXmlApplicationContext负责读取xml内容通过getBean(beanName)的方式获取 bean

3,@Configuration

用于类上面,相当于xml配置文件中的beans标签。负责读取配置类。@Configuration注解的配置类有如下要求:

@Configuration不可以是final类型、@Configuration不可以是匿名类、嵌套的@configuration必须是静态类

4,@Bean注解

@Bean相当于xml配置文件中的bean标签。用于方法上,注入bean实例。通过@Bean的形式是使用的话, bean的默认名称是方法名。若@Bean(value="bean的名称")。那么bean的名称是指定的。

读取容器中的bean:AnnotationConfigApplicationContext;

@ComponentScan

光生明注解是不可以使用的,必须让Spring扫描到才可以被使用.扫描com.jdyun.admin.annotation包下面的类

@ComponentScan(basePackages = {"com.jdyun.admin.annotation"})

排除用法:也可以去除某个注解不被扫描

excludeFilters属性去除某个注解不被扫描

@ComponentScan(basePackages = {"com.jdyun.admin.annotation"},excludeFilters = {

@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),

@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {JdyunService.class})

})

type = FilterType.ANNOTATION,value = {Controller.class}表示Controller注解不被扫描

(type = FilterType.ASSIGNABLE_TYPE,value = {JdyunService.class}表示自定义的类不被扫描

包含用法:包含某些类或注解

包含用法 includeFilters ,注意,若使用包含的用法,需要把useDefaultFilters属性设置为false(true表示扫描全部的)

这里需要补充一个重点:如果includeFilters 使用的是自定义的过滤规则.并且useDefaultFilters=false那么就不会走ComponentScan默认的过滤规则.假设@Controller或者@Compontent等注解不符合自定义的过滤规则.则不会被扫描到.更不会被注入到Spring容器内.如果符合自定义规则的类.即使没有Compontent等注解也会被扫描到并且注入到Spring容器内.


@Configuration

@ComponentScan(basePackages = {"com.tuling.testcompentscan"},includeWSFilters = {

@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, Service.class})

},useDefaultFilters = false)


以上包含Controller注解以及Service注解。



@ComponentScan.Filter type的类型

1注解形式,FilterType.ANNOTATION    例如自定义注解或者@Controller @Service 等等等

2指定类型,FilterType.ASSIGNABLE_TYPE

3aspectj类型的,FilterType.ASPECTJ(不常用)

4正则表达式的 FilterType.REGEX(不常用)

5自定义枚举类型


自定义类型的使用

自定义注解类需要实现TypeFilter并且实现一个match方法

@Override

public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

//获取当前类的注解源信息

AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

//获取当前类的class的源信息

ClassMetadata classMetadata = metadataReader.getClassMetadata();

//获取当前类的资源信息

Resource resource = metadataReader.getResource();

if(classMetadata.getClassName().contains("dao")) {

return true;

}

return false;

}


配置Bean的作用域对象@Scope(value = "prototype")

设置Bean的作用域使用@Scope,@Scpoe有四个值。

1,singleton 单实例的(默认),而且是饿汉加载。容器启动实例就创建好了。所有的bean都是单实例的bean

2,prototype 表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用的时候才会创建)。

3,request 同一次请求

4,session 同一个会话级别

@Lazy

Bean的懒加载@Lazy(主要针对单实例的bean 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)


@Conditional进行条件判断等.

1,@Conditional注解是什么

@Conditional注解是条件判断注解,可根据一些自定的条件确定是否加载Bean到Spring 容器中,看过springBoot源码的同学会发现,springBoot中大量使用了该注解.

2,@Conditional注解如何使用

自定义的@Conditional注解需要实现Condition接口(自定义类CustomerCondition).并且实现一个boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)方法.比如可以在该方法内写一段逻辑返回true

if(context.getBeanFactory().containsBean("StudetnAspect ")) {

return true;

}

return false;

自定义注解定义完以后在某个方法上使用自定义的Condition

public class MainConfig {

@Bean

public StudetnAspect studentAspect() {

return new StudetnAspect ();

}

//当切 容器中有StudetnAspect 的组件,那么StudetnAspect 才会被实例化.

@Bean

@Conditional(value = CustomerCondition.class)

public School buildSchool() {

return new School ();

}

}

当加载buildSchool方法的时候,使用条件注解@Conditional(value = CustomerCondition.class),如果CustomerCondition中返回true.那么就创建School对象.总之使用@Conditional注解,需要实现Condition接口.可以在实现方法中写入自己的判断逻辑.这个判断逻辑是跟你使用该注解的方法息息相关.

@Conditional用在方法上只能是一个方法注入一个bean实例,所以@Conditional标注在方法上只能控制一个bean实例是否注入。

@Conditional用在类上会注入一批bean的实例,如下代码所示

@Conditional({CustomerCondition.class})

@Configuration

public class BeanConfig {

@Bean(name = "Student")

public Student student1(){

return new Student();

}

@Bean("Student")

public Student student2(){

return new Student();

}

}

如果CustomerCondition条件为true的话,那么会注入student1和student2两个bean实例

多个条件类判断如下:

@Conditional({CustomerCondition.class,ObstinateCondition.class})

@Configuration

......

判断规则是:

1,CustomerCondition返回结果为true ObstinateCondition返回结果为false 那么不注入.

2,CustomerCondition返回结果为true  ObstinateCondition 返回结果为true 则注入.


往IOC 容器中添加组件的方式

1:通过@CompentScan +@Controller @Service @Respository @compent

2:通过@Bean的方式来导入组件(适用于导入第三方组件的类)

3:通过@Import来导入组件 (导入组件的id为全类名路径)

例如:

@Configuration

@Import(value = {Person.class, Car.class})

public class MainConfig {

}

4:通过@Import 的ImportSeletor类实现组件的导入 (导入组件的id为全类名路径)

public class DemoImportSelector implements ImportSelector {

/可以获取导入类的注解信息

@Override

public String[] selectImports(AnnotationMetadata importingClassMetadata) {

return new String[]{"com.demo.Car"};

}

5:通过@Import的 ImportBeanDefinitionRegister导入组件 (可以指定bean的名称)

public class DemoBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

//创建一个bean定义对象 RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class);

//把bean定义对象导入到容器中 registry.registerBeanDefinition("car",rootBeanDefinition); }

}

@Configuration //@Import(value = {Person.class, Car.class}) //

@Import(value = {Person.class, Car.class, DemoImportSelector.class})

@Import(value = {Person.class, Car.class, TulingImportSelector.class, DemoBeanDefinitionRegister.class})

public class MainConfig {

}

6:通过实现FacotryBean接口来实现注册 组件


Bean的初始化方法和销毁方法.

什么是bean的生命周期?

1,bean的创建----->初始化----->销毁方法:由容器管理Bean的生命周期,我们可以通过自己指定bean的初始化方法和bean的销毁方法

@Configuration

public class MainConfig {

//指定了bean的生命周期的初始化方法和销毁方法.

@Bean(initMethod = "init",destroyMethod = "destroy")

public Car car() { return new Car();

}

}

需要注意的是:

1, 针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法

2, 针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受 IOC容器的管理..

2,通过 InitializingBean和DisposableBean 的二个接口实现bean的初始化以及销毁方法

3,通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法

4,通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程

1, postProcessBeforeInitialization 在init方法之前调用

2, postProcessAfterInitialization 在init方法之后调用

5,通过@Value +@PropertySource来给组件赋值


自动装配

1,Autowired

1,Autowired 的使用以及介绍

Autowired 默认按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照 属性名称来进行装配.比如容器中有两个DemoDao,

一个叫DemoDao1另一个叫DemoDao2

@Autowired

private TulingDao DemoDao1; 装配第一个组件

@Autowired

private TulingDao DemoDao2; 装配第二个组件

2,假设我们需要指定特定的组件来进行装配,我们可以通过使用@Qualifier("demoDao")来指定装配的组件, 或者在配置类上的@Bean加上@Primary注解

@Autowired

@Qualifier(" demoDao  ")

private DemoDao DemoDao2;

3,假设我们容器中即没有tulingDao 和tulingDao2,那么在装配的时候就会抛出异常

No qualifying bean of type 'com.jdyun.testautowired.DemoDao' available, 若我们想不抛异常 ,我们需要指定 required为false的时候可以了。

4,@Resource(JSR250规范)

功能和@AutoWired的功能差不多一样,但是不支持@Primary 和@Qualifier的支持

5,@InJect(JSR330规范)

需要导入jar包依赖 功能和支持@Primary功能 ,但是没有Require=false的功能

1,使用Autowired 可以标注在方法上(标注在构造函数上/标注在set方法上/标注在方法的入参)


1:通过@Profile注解 来根据环境来激活标识不同的Bean

1,@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效

2,@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活

3,没有标志为@Profile的bean 不管在什么环境都可以被激活

如果使用@PropertySource(value = {"classpath:ds.properties"})注解 可以实现EmbeddedValueResolverAware类来获取属性

激活切换环境的方法

方法一:通过运行时jvm参数来切换 -Dspring.profiles.active=test|dev|prod

方法二:通过代码的方式来激活

封面图源网络,侵权删除)

如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

一大波微服务、分布式、高并发、高可用的原创系列文章正在路上,

欢迎关注头条号:java小马哥

周一至周日早九点半!下午三点半!精品技术文章准时送上!!!

十余年BAT架构经验倾囊相授

学习视频资料限时领取

死磕Spring源码-常见底层核心注解相关推荐

  1. Spring源码系列(十三)——Spring源码编译及详细注解

    文章目录 1. 环境搭建 2. 代码编译 2.1 编译代码 2.1.1 build.gradle 2.1.1.1 第一处 2.1.1.2 第二处 2.1.2 gradle.properties 2.1 ...

  2. Spring源码解析之@Component注解的扫描

    阅读须知 Spring源码版本:4.3.8 文章中使用/* */注释的方法会做深入分析 正文 承接Spring源码解析之context:component-scan标签解析,下面就是扫描的流程: Cl ...

  3. 死磕JDK源码之String

    String本质是对char数组的封装 Serializable接口 实现Serializable接口的类可以被序列化 Comparable接口 实现Comparable接口的类可以支持排序,需要重写 ...

  4. spring源码分析之cache注解

    Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如EHCache 或者 OSCache),而是一个对缓存使用的抽象 ...

  5. Spring源码解析之-- 事务TransactionInterceptor 分析(开启事务)

    目录 一.介绍 二.TransactionInterceptor 分析 2. 流程 2.1 invoke 2.1.1 TransactionAspectSupport#invokeWithinTran ...

  6. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

  7. 【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

    [Spring源码系列- IOC] 1 [Spring源码]0.安装Gradle环境 2 [Spring源码]1.下载与编译_pom relocation to an other version nu ...

  8. Spring源码学习(三)-- 底层架构核心概念解析

    前面,我们大概了解了Spring中的一些概念和底层工作流程,这篇是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习.​ BeanDefinition BeanDe ...

  9. Spring源码分析(二):底层架构核心概念解析

    本节主要介绍一下Spring底层中用到的"基础设施",是后续看Spring源码所必备的,防止后续看源码的过程中,遇到不会的概念得单独跳出来学习. BeanDefinition Be ...

最新文章

  1. 力扣(LeetCode)刷题,简单题(第9期)
  2. 科普丨深度学习引擎的终极形态是什么?
  3. c ef框架-mysql_.net EF框架 MySql實現實例
  4. javascript转换金额格式
  5. 深度学习-Tensorflow2.2-深度学习基础和tf.keras{1}-优化函数,学习速率,反向传播,网络优化与超参数选择,Dropout 抑制过拟合概述-07
  6. 计算机的好处英语,跪求一篇英语作文 题目:论计算机的优缺点
  7. Equalize the Remainders(set二分+思维)
  8. .NET Core很酷,你不得不知
  9. C# 中使用面向切面编程(AOP)中实践代码整洁
  10. enumset_枚举集合的EnumSet
  11. DCC-GARCH模型及动态CoVaR计算 案例与代码
  12. 在.net2.0下使用System.Web.Script.Serialization;
  13. jar转apk专辑 android,jar转apk格式转换器
  14. 机械电子工程专业和计算机科学,机械电子工程专业属于什么类别
  15. 收藏!从十篇顶会论文解读计算机视觉的未来之路!
  16. python中空字符串是什么_python为空怎么表示 python如何判断字符串为空
  17. 第五---七章 交换机和路由器的基本配置
  18. vue 节流throttling防抖debounce
  19. maven核心,pom.xml详解
  20. 网站响应速度慢,这些原因不可不知?

热门文章

  1. PennyLane 量子神经网络QNN预测sin函数
  2. 小白玩PVE proxmox RX560D显卡直通
  3. 亿信华辰亮相2020华为全联接大会,共创行业新价值
  4. 从蜜罐发展看攻击欺骗应用趋势(好文章)
  5. Hack The Box-Redeemer关卡
  6. hack games
  7. ucore lab 6
  8. 【开源项目】minimp3 MP3解码器
  9. 边玩边学HTML和CSS
  10. 知识图谱关系抽取 python_中文知识图谱-基于规则的关系抽取