spring源码_功能实现分析

1 篇文章 0 订阅
1 篇文章 0 订阅

Spring源码分析从功能到实现

1.Spring核心功能.

官网介绍的spring核心技术,包括以下这么多,包括ioc容器,aopAPIS,spring的切面编程等等.spring框架,很庞大,实现的功能很多,很多细节代码也完善了各种坑.源码慢慢看,设计思路,代码的设计模式,算法,慢慢看.
    先理解一下控制反转的思想
    https://blog.csdn.net/ivan820819/article/details/79744797,
    介绍了ioc思想的由来.简单说就是,为了解决对象之间耦合度的问题.提出了"控制反转思路",由主动获取依赖,变成被动获取依赖,控制权交给别人.
    ==>获得依赖对象的过程被反转了.
    ==>齿轮关系图,就很清楚的表达了问题.
    ==>最后,我们只需要关心,对象本身和容器就可以了.解决了对象之间的耦合性. 

1585023848026

1585025423917

1585025437338

2.Spring的主要功能如何实现.

2.1 对象管理

2.1.1 业务分析
主体功能:扫描所有包,获得每一个对象的信息,实例化所有对象,完成依赖的注入,放入容器,等着被调用.

难点:如果只扫描几个类,创建一个容器,再直接管理,这个过程是比较容易的.如果有很多的类,需要管理bean,包括一些jar包.那么就得为容器准备一个合适的创建过程.因为每一个步骤,都有各种小问题需要解决.

如
1.扫描包.整理成beanDefinition 
(获取每个对象的信息,依赖信息@autowire,其他配置信息@import.@Bean)
哪些对象可以称为Bean(@component,@resouce),需要不需要对某些bean进行过滤,比如@Conditional 

2.什么方式创建对象.
==>构造器? 
==>工厂Bean?  
    1).一些Bean的创建,普通的构造器完成不了功能. 
    2).一些Bean,想要批量创建,可以使用
==>如果有多个构造器?推断构造方法.

3.依赖关系(set,constructor) 
  1). 自动装配@Autowire 
  2). 自动装配4种方式
  依赖注入的方式? set方法?构造器方法?(反射也属于set的变体.)  
官网有介绍:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-dependencies

4.注入容器


简而言之,需要创建一个合理的过程,完成容器的创建. 
2.1.2 需要考虑,解决的问题
这里,关注spring对于业务,设计出来的解决流程.OO思想.设计模式.代码的高效执行(缓存,安全)
不关心他某些问题的具体处理细节,逻辑代码,比如推断构造方法,asm操作等等.
1.扫描环境,创建所有的beandefinition.
1.我得扫描所有文件,我还得提供接口让用户也能参与扫描文件的过程. 这两个操作有没有先后顺序.?
如果在开过过程中,或者后续扩展过程中,我还需要提前做些.准备工作.而且不仅仅是需要一些扫描,还可能各种初始化配置,等等.
==>spring,抽象出了BeanDefinitionRegistryPostProcessor 这个对象. 专门用来处理创建/整理BeanDefinition的动作.
BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子类,说明,这个类还可以有配套的后置处理方式.不用创建多个类.

BeanDefinitionRegistryPostProcessor  用面向对象的角度想,这个对象是用来扫描bd的.创建bd.
spring,自己是准备了configurationclasspostprocessor处理扫描,用户自己可以实现这个接口.
加入到这个 创建beanDefinition的过程中去.


那么这里设计的,创建bd的代码,就得保证
1.用户能参与.   
	那么 BeanDefinitionRegistryPostProcessor,一定不是查询到之后,只执行一次的,先通过一个,找到其他扩展的,那么就得对 BeanDefinitionRegistryPostProcessor 进行扩展,相当于,一个处理内部的,一个处理用户的.
	我们可以这样,从容器中,找到我们特殊的BeanDefinitionRegistryPostProcessor,比如,继承更多接口的,order?.依赖这个,先执行我们自己的. 然后再去找用户的.
	==>既然用户能参与,那就得我的ioc容器,先找到他们.然后在执行
	==>代码如何设计呢?
2.后期可扩展.
	已经抽象成BeanDefinitionRegistryPostProcessor动作了,方便扩展
3.创建操作有执行顺序.
   

DiY_创建bd操作   implements    BeanDefinitionRegistryPostProcessor  ,order.
或者
DiY_创建bd操作   implements    BeanDefinitionRegistryPostProcessor  

//伪代码

createbeandefinition( 
//1.先执行,ioc初始化过程 Registry   BeanDefinitionRegistryPostProcessor 
  依赖,这个找到,用户添加的BeanDefinitionRegistryPostProcessor.
  要不然用户的信息,也不可能加入到容器中.不可能让他提前扫描.
  ==>所以,这里就是系统先执行自己的BeanDefinitionRegistryPostProcessor,来完成bd的扫描创建  
  ==>比如,去容器找复杂,我们自己的BeanDefinitionRegistryPostProcessor,去完成bd的创建
  
  
  //2.执行扫描到的  BeanDefinitionRegistryPostProcessor
}
当然,这里的代码,如果更细化,那么可扩展性就能得到提升,具体看源码
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()

1587643005129

1587643656850

​ PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

处理bd的核心方法

1587641421273

1587641918248

总结:
以上,完成了 "创建bd" 这个动作的设计.
满足了,程序易扩展(用户可以扩展自己的功能),
易维护(二次开发).

2.spring 如何创建bd的
1.第一种,spring内置的BeanDefinitionRegistryPostProcessor.
spring提供
configurationClasspostProcessor负责完成扫描,这个后置处理器负责找找配置类,然后扫描出来.
 ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
==>校验配置类
目标:需要校验beanDefinition,是不是配置类. 准备一个ConfigurationClassUtils(容器里有很多bd,要找到配置类)
      ==>元数据载体
	  目标:解析功能,要分析注解. 创建AnnotationMetadata 的接口,按照功能写具体实现类,或者扩展
	  创建AnnotationMetadata,职责就是,作为注解数据载体.分析记录Bean相关的注解信息,并且
	        ●  为了服务Annotation  AnnotatedElementUtils  创建了工具类. 比如向上递归查找,是否有某			    
			●  为了记录每一个注解的内容,包括注解属性值,提供api获得属性值,或者他就干脆继承了hashmap.把属			
			性值作为一个整体,按照功能拓展他.AnnotationAttributes
	        ●  当然,为了表达其他功能,比如,排序,比如异常.可以放在一个包里,专门表达注解相关的东西.
	  ==>元数据读取		
		目标:读取功能  MetadataReader  asm操作.
		正常我们通过,反射,可以获得类的字节码信息,在获得每一个方法的注解信息. 前提是这个类已经被初始化.
		 但是,spring的一些工能,不允许我们直接实例化一些类,因为有些类,还没有经过类加载阶段,还是class文件.比如,一些@conditionclass.(x.class)   而且全都反射,也是不安全的操作.还得把所有类都经过类加载阶段.所以,spring,通过asm操作的方式,获得字节文件,再去筛选获得各种原信息. 我们知道,class文件内容,包括,魔数啊,方法表,常量池,每个方法对应的指令,类的各种信息等等,都是16进制文件里.
		在你了解class文件结构,就可以通过asm.来操作.==>如果以后需要这种能力,再去看asm框架.


==>解析配置类	   
目的:需要解析功能,准备一个解析器ConfigurationClassParser.解析配置文件.找到Bean
	
	==>条件功能
	 因为了提供了 @conditionBean  @ConditionClass 功能. 所以,会先校验你这个配置类,该不该解析
	 ConditionEvaluator	这个类,处理条件问题.当然,校验bean,校验class,直接去容器里找,类加载器里面找.
      提供条件筛选功能.
	  
	==>扫描功能  
     目的:提供了@Component 功能,所以得完成批量扫描功能.
      		●  创建component的扫描器.去负责扫描包.所有,找到符合条件的bean.(@component @configuration. 等等)   
			ComponentScanAnnotationParser    ClassPathBeanDefinitionScanner
		    ●  得进行筛选,(过滤掉非bean的类) 功能
		    fileter   TypeFilter
           当我们,自己想要实现扫描包,并且筛选出bean的时候,我们就可以修改这个过滤器规则
	     这部分代码给人的感觉就是,面向接口编程. 主要核心功能,不变的,写在父类里面,功能大概写在接口里面.
         按扩展内容,进行扩展.  比如,mybatis的自定义扫描,就是扩展这里的东西.     
            ●  按照提供的功能@import @import  importselector @Bean  写业务代码.   
    


2.第二种,当然就是,BeanDefinitionRegistryPostProcessor 继承合适,接口.然后自己创建bd的.
         看到相应框架直接去处理就ok. 

校验配置类

1587708194025

1587708210415

元数据载体

1587708299259

1587708308395

1587708313646

元数据读取

1587708594345

1587708645242

1587708690348

扫描配置类

1587708939694

1587708990060

1587709094011

1587709135949

1587709240988

1587709478140

3.spring 通过 beanfactoryPostProcessor 处理,扫描出来的bd
1.前面扫描,创建bd,对bd只是执行了初始赋值. 还可以对bd 进行处理.赋值,以及对beanfactory的数据进行处理.
没看到有什么特殊重要的事.顶多是,对@configuration 的类,创建了代理类. 让@Bean方法获得的对象全局一个.

1587709969790


至此,spring的BeanDefinition 的信息,处理完毕.

4.完成Bean的创建
这部分,完成每一个Bean 的创建.如果是,正常面向过程的敲代码,就是,一路执行到底,所有加工过程,一点一点的来.bean的创建是一个复杂的过程,我需要代理,我需要解析注解,我需要找到所有切面,我不想走bean的生命周期,我想添加属性值==>把所有bean的操作,封装成一个一个BeanPostProcessor. 方便扩展,和加入功能.==>oo思想==>Bean对象的创建●  调用构造方法创建.●  如果有多个构造方法就推断   这推断方法,就相当于,一种算法,相当于面对一个业务,如何解决掉.●  如果注入方式是构造器自动注入.那么就执行那些对象的生命周期.==>Bean完成属性注入之前,可以处理的事->创建出来一些bdpp比如InitDestroyAnnotationBeanPostProcessor  完成生命周期回调数据整理 封装成LifecycleMetadata比如AutowiredAnnotationBeanPostProcessor    完成,自动注入内容的完成. 封装成InjectionMetadata可以理解为,在完成注入之前,我提供一些对bean的操作,我可以是整理数据,填充数据 等等.就是对所有bean的操作进行一个分类,提供一个执行顺序,类似BeanDefinitionRegistry的设计.==>Bean属性的注入对用户提供了,几种注入的方式. name class 无,构造方法 @Autowire     ==>@Autowire 走的是AutowiredAnnotationBeanPostProcessor 后置处理器,他去完成属性注入,并通过field.set,赋值属性,走的是AutowiredAnnotationBeanPostProcessor去完成获得属性值,以及赋值	==>自动装配.	通过自省方法,找到自己的set方法,然后bean工厂去找值.这部分功能,可以直接交给beanfactory来做,属于创建对象的范畴.	==>bean的生命周期回调和代理.代理模式: 切面的设计  这个在后面会单独分析.属于嵌入功能.总结: 围绕BeanPostProcessor进行设计.对内,为了完成bean的操作,设计出相应的类和方法.对外,包装成一个某种类型的bean操作.

处理一部分后置处理器.

1587713757052

  比如InitDestroyAnnotationBeanPostProcessor 为了 整理 LifecycleMetadata  生命周期元数据 .  buildLifecycleMetadata(clazz); 构建者模式找到.	

1587713478636

AutowiredAnnotationBeanPostProcessor 找到所有 自动注入的元数据@AuwowireInjectionMetadata

1587713590765

1587713603389

AutowiredAnnotationBeanPostProcessor 去完成 @Autowire 内容的注入.提供 字段注入,method注入.成员属性走字段注入,如果是构造方法的自动注入  就是方法上加@autowire  那就走下面那个.把相关功能设计成内部类.AutowiredAnnotationBeanPostProcessor 交给内部类  AutowiredFieldElement 完成注入他需要对象值,那就交给工厂类获得属性值.

1587716097839

交给beanFacoty来完成属性值的创建,合情合理,因为,工厂负责生产对象.负责bean的生命周期

1587716209326

2.1.3 Spring.ioc的大概执行过程.
关键对象:BeanDefinition.  容器中对象的数据结构BeanDefinitionRegistryPostProcessor    依靠这个去扫描文件BeanFactoryPostProcessors            BeanDefinition扫描之后,需要的处理BeanDefinitionBeanPostProcessors 			        完成每一个bean的创建过程.
整个过程:基础对象准备(如beanfactory)------------------------扫描并创建bd------------------- 处理已经注册在beanfactory中的BeanDefinitionRegistryPostProcessor,利用策略模式,执行各种类型的 BeanDefinitionRegistryPostProcessor. 其中:    1).ConfigurationClassPostProcessor 类,完成了各种@configuration@component,@Import,@Bean,各种bean的BeanDefinition的创建.   内部解析器,递归,创建.  2). ------------------------后置处理bd---------------------处理已经注册在beanfactory中的BeanFactoryPostProcessors,利用策略模式,执行各种类型的BeanFactoryPostProcessors1).比如,@configuration,再这里完成了代理.------------------------实例化Bean---------------------执行一系列的后置处理器,完成bean的创建.1).InstantiationAwareBeanPostProcessor 调用这种类型的后置处理器,完成TargetSource类型对象的创建.当然为了完成一些过滤信息的判断,会查询已有bd,并且会把过滤信息进行缓存.2).利用构造器,创建bean.   如果,有多个构造器或者自动装配模式为构造器装配,会推断构造方法.3).创建bean之后,开始解析MergedBeanDefinition,将bean的其他信息,准备好,@Autowire,@Init,等等准备好.4).解决循环依赖,如果支持,就将自己先放入"某种类型工厂" ,  	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));  	先判断,是否允许循环依赖==>向context中,添加factory方法,用来产生bean,防止循环调用逻辑出问题.5).属性注入,自动注入,手动注入都有6).初始化bean,最后一步,完成,生命周期回调,代理对象创建.看代码,就都想出来,不用记他的顺序,只要记"----"部分即可    
2.1.4 可以学习的思路
1.OO思想
1.关于BeanPostProcessor接口设计

1587792338451

1587718489330

1587777687684

1587777731825

就拿BeanPostProcessor 举例子.

顶级接口 BeanPostProcessor   功能 :实例化之前处理实例化之后处理

1587778219309

子接口  DestructionAwareBeanPostProcessor	 销毁后置处理器功能 :在销毁之前处理是否需要删除

1587778265292

 子接口       InstantiationAwareBeanPostProcessor    实例化后置处理器 功能: 实例化之前处理 实例化之后处理 处理属性值.(类的properties,没见有什么特殊的赋值)

1587778296766

子接口  MergedBeanDefinitionPostProcessor后置处理beandefinition   :  处理bd数据用的,比如找到 InjectionMetadata  LifecycleMetadata 重置beandefition  : 当有一些数据,有问题,想删除什么缓存,想清除什么数据,这就是一个方式.

1587778359892

第二层接口  SmartInstantiationAwareBeanPostProcessor   聪明的 实例化 后置处理器添加功能:1.推断备选的构造方法2.getEarlyBeanReference: Obtain a reference for early access to the specified bean,	  typically for the purpose of resolving a circular reference.                        获取指定bean的早期访问引用,                        通常用于解析循环引用。3.预测bean的类型.  比如,代理功能,通过beanclass,和beanName,我需要知道原始bean的class  比如,factoryBean,通过beanclass,和beanName,我需要知道原始bean的class或者工厂的class,工厂classname加+比实例化InstantiationAwareBeanPostProcessor更具体的    实例化功能,服务于实例化 的功能.

1587778633736

1.描述bean后置处理器的功能. 设置顶层接口,按照要实现的功能,比如实例化,销毁,处理bd,按照功能,设置子接口.>职责 具体化.>如果还能具体化,在添加一层接口.

围绕处理bean的功能,设置一组接口类. 用接口描述功能.

接口类型就相当于一个,类的一个标志,在bean执行生命周期的时候,可以通过这个接口执行具体功能.

该类可以继承其他类,来补充自己的能力,活着继续扩展.看情况定.总而言之,接口可以理解为一种标记

比如bean的生命周期过程:

InstantiationAwareBeanPostProcessor先执行实例化之前的接口方法

1587791421607

1587791455861

执行MergedBeanDefinitionPostProcessor 相关的接口

1587791503380

执行smartinstation 相关的

1587791528491

1587791541864

等等.

2. 类,抽象类,的设计.
用Proxy,AspectJAwareAdvisorAutoProxyCreator功能举例子.一个服务于切面创建的实现类,他的功能,一定有多个实现者共同完成.全部冗杂在一个类里面,显然要爆炸.先记录他的功能.1.通过他继承的BeanPostProcessor的类型来看,他服务于bean的生命周期阶段.实现接口,标记有这个功能,在spring里面,在合适的时候,被调用.2.AopInfrastructureBean也是为了作为一个标记.作为基础建设类.他会在是否过滤掉的时候,基建类,我也忘了在哪判断,不用多做附加判断. 当做是一个标记.服务于某个功能3.aware 类接口,包括BeanClassloader BeanFactoryAware. 服务于 属性值赋值 功能. spring可以在某个阶段,执行相应的aware接口,完成属性值的赋值. 4.Aop功能==>AopConfigConvenience superclass for configuration used in creating proxies,to ensure that all proxy creators have consistent properties.方便的超类配置用于创建代理,确保所有代理创建者具有一致的属性。Aop功能的基础属性字段    以及字段的set方法    get方法->is方法  直接变成判断了==>ProxyProcessorSupport Base class with common functionality for proxy processors, in particular ClassLoader management and the {@link #evaluateProxyInterfaces} algorithm.具有用于代理处理器的公共功能的基类,特别是类装入器管理和{@link #evaluateProxyInterfaces}算法一些判断功能的类.和基础属性区别开. 这个带有些许计算功能==>AbstractAutoProxyCreatorBeanPostProcessor implementation that wraps each eligible bean with an AOP proxy, delegating to specified interceptors before invoking the bean itself.  用AOP代理包装每个合格bean的BeanPostProcessor实现,在调用bean本身之前委托给指定的拦截器。抽象类,服务于创建代理类.比如,我们完成代理功能.     ->需要构建切面 advisors 还得缓存advisor 有切面就得有切点相关的.当然切面可以封装在advisor里面.     ->创建代理类.     ->判断bean是否需要代理     ->一些beanPostProcessor的功能     ->一些服务于创建代理类需要的属性值     ->各种农判断功能,随着功能越来越完备.会越来越复杂.     ==>具体的实现类了,按照功能,再细致 比如AnnotationAwareAspectJAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreatorInfrastructureAdvisorAutoProxyCreator==>这么理解1.功能嵌入到ioc容器中你要完成代理功能,那么你的代理功能就得实现合适的BeanPostProcessor 加入到bean的生命周期.如果想加入实例化前后,就实现smartinstation,销毁功能,就加入destory,需要在哪里嵌入,就实现什么样的接口.2.代理功能的完成.   完成代理功能,是一个很庞大的过程.比如,你构建了advisor,pointcut,校验,扫描,那么你的功能类就会很庞大.所以要合理"创建"这个功能   ->基础属性拆到一个类   ->基础功能拆到一个类   ->标准工能拆到一个类   ->具体功能,主类创建	我认为这部分,就是实际实现代码的设计了. 最不济通过,面向过程的思路,把代码先顺序执行完,实现功能,在根据设计模式,进行拆分,设计类.	那么基本上,如果底层都知道了,我至少写代码就是个顺序执行的过程.->提代码,大块代码,都可以给他提出来,每一个方法,越短越好,别问我为什么.  哪怕是帧栈消耗过大,也拦不住我->面向对象,利用设计模式,把一些有相同特征的事物,或者围绕一个中心的事务,能提,就提出来.->设计模式,对业务进行设计,利用设计模式,更好的设计之间的关系.写出来合理的代码.      比如 builder思路 Facoty思路.面向功能开发,面向对象开发!!!!!!!

1587792493885

Aopconfig

1587793317879

ProxyProcessorSupport

1587798126969

3.接口设计

aware 接口的设计

为了类的一个成员属性的设置.为了完成一批类的成员属性的设置.为了完成的成员属性,在某一个时间段全部设置完.为了,当某个对象创建完,需要赋值给众多类的时候,能够找到这些类,完成功能可以让他们都实现一个接口,找到所有类,同时执行aware的方法.完成设置.接口可以满足一批类的一个功能.接口作为一个标记!!!

1587728714516

AopInfrastructureBean

Marker interface that indicates a bean that is part of Spring's  AOP infrastructure. In particular, this implies that any such bean  is not subject to auto-proxying, even if a pointcut would match.    也是一个标记作用.

BeanpostProcessor 设计.

3.Spring其他功能的实现.

3.1 Aop切面功能(@Aspect)

3.1.1 功能概述
1.从注解配置角度查看,Aop的功能.@Aspect  切面声明  --> 标记一个切面类.@pointcut  切入点@before @after @....  修饰方法的   方法的哪个位置插入    他必定得配套切入点信息,因为他修饰怎么通知方法,没说,要通知哪些方法  以上是,aop功能提供的注解.而且还有advisor 方式。2.核心功能aop功能,最后组成的数据结构Advisor   切面PointCut  切点
3.1.2 如何实现
1.切面代码,如何添加到我们的bean中?  1). 在bean的生命周期之后,执行beanPostProcessor的时候,利用动态代理,把切面添加进去。(什么是动态代理,什么是静态代理,代理模式需要完成什么内容,cglib,jdk)  2).在哪添加这个后置处理器???   他是合实例化之后相关的,所以在生命周期之后,执行对应的后置处理器就行.后置处理器,可以通过@Import, importselector 等方式,加入到容器中2 如何让ioc容器,知道开启了aop功能,并且能完成扫描,完成代理。查看@EnnableAspectJ.. 那个注解就知道了.就通过一个注解,或者什么,触发这个功能.3.@EnnableAspectJ..开启功能之后,需要找到"基建类",AnnotationAwareAspectJAutoProxyCreator也就是配置切面的类.那么就得找到所有的advisor,以及所有advisor的切面类,以及切面对应的切入点pointcut. 难点在于解析这个匹配关系,咋说得搞点什么算法什么的. 3.如何记录每一个方法的切面情况.在执行每一个bean的生命周期的时候,循环每一个方法,在循环每一个advisor,去匹配他的pointcut.并且缓存.4.当切面已经标记好了,如何执行.利用动态代理,把所有切面封装在一起,作为一个intercept.当代理对象执行的时候,就会执行我们的所有切面.5.方法的切面的执行顺序如何保证.@Before @Aroud @After @Transactional  链式编程+调度器==>这里自己写代码,实现这个链式编程想到这个地步,我们完全可以脱离spring源码,简单的实现一个aspect 功能代码任务:  手写aspect 功能  嵌入到spring功能手动实现,aspectj的功能. 可能实现不了.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1.扫描    1).扫描所有的包.    	->spring扫描所有包,利用configuration那个后置处理器.在所有已经扫描出来的beanDefin    	从容器中包括@CuaAspectJ,利用BeanFacotyUtils找到我们需要的bd    	->如果是mybatis扫描bean,就得自己写扫描包了,总不能都加@component->BeanFacotyutils需要beanFacoty 那就 继承BeanFacoty接口,有这个参数.然后利用工具		类,找到所有beanName.    2).找到Proxy功能的类 比如@AspectJ       //spring有这个功能    3).创建基类.2.解析    1).解析基类,找到所有advisor.    2).为advisor,整理pointcut3.创建代理对象    1).递归类的所有方法,找到每一个方法,循环每一个切面,通过切点,缓存所有method对应的切面.    (因为切面的切入点是方法级别的)    2).创建代理类,所有的切面封装为一个intercept(内部切面执行顺序,自己写方法控制),    3).执行代理对象

1587799584360

1587800495739

1591103384659

当开启 aspectJ  切面功能的时候.  会注入 AnnotationAwareAspectJAutoProxyCreator   这个后置处理器去完成,扫描Aspect 类型的切面, advisor 类型的切面. ==>  最后都转化成advisor其中,的转化过程.如果细看他的实现,到处都是设计模式,和设计细节.

1591103462499

确认是aspect 切面后,将创建advisor 类 放进所有切面中.

1591103742645

在每一个Bean的生命周期后期,会判断是否需要创建代理类,这个时候,会循环advisor中,去寻找自己的类,

有没有配置切面. (每一个advisor中,的pointcut 的matches 能否匹配到我的类,我的方法.如果有 method<->切面类相对应, 执行方法的时候,会判断,你这个类对应了几个切面,然后按照一定的顺序执行. 创建代理类,会缓存 类对应哪些切面. 缓存,方法对应哪些切面.记不住了,可以debug 切面的执行路线. )

1591147840281

1591148667555

在生命周期之后,进行 advisor->pointcut->matcher->parse 去解决匹配信息,这里代码不想看.头疼.

1591149703974

3.1.3 可以学习的思路

1.在执行切面的时候,链式编程+调度方法

2.method-advisor-pointcut 之间的缓存关系设计.

3.InfrastructureAdvisorAutoProxyCreator . 负责扫描切面信息的创建者的 创建方式可以学习.

通过优先级选择创建者,优先级通过初始化数据获得值. 点方法进去看看就知道了.算是代码技巧了

4.pointcut 类设计(配置缓存类,配置扫描器,OO思想)

5.通用的扫描器,只需要修改过滤器,就可以完成Set parser

3.2 spring事务管理(@Transactional)

功能: 添加@Transactional 完成事务功能.如何实现: ==>实际上,事务功能,就是为bean,再添加一个拦截器就可以了.查看@EnableTransactionalManagement 就知道了.1.创建合适的后置处理器,完成扫描.@Transactional事务的连接事务的隔离级别事务的传播特性,这些都在代码里面当做业务处理就ok了. 比如事务的连接,是放在 DataSourceTransactional啥啥一个同步事务管理里面. threaLocl对象保存的,和mybatis集成的时候,连接就放那儿. 剩下两项,都是业务代码.2.嵌入ioc容器的方式,和aspectj 方式差不多

3.3 缓存功能.

功能: 添加@caching 完成事务功能.如何实现:  本质上,就是在bean上面,添加一个切面. 得自定义扫描器把@caching相关的注解扫描到.看看@EnableCaching是怎么实现的就知道了.

3.4 如何与Mybatis 集成.

3.4.1实现过程
功能: 把Mybatis中,为每一个Mapper准备的DaoMapper,加入到spring容器中,并且能够完成自动注入.   String resource = "mybatis.cfg.xml";      Reader reader = Resources.getResourceAsReader(resource);     SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader);//工厂模式+构建者模式,     SqlSession sqlSession = ssf.openSession();    Mapper mapper = sqlSession.getMapper(mapper.class)思路: 0.先明白mybatis中,实例mapper的过程.1.DaoMapper,需要走mybatis的逻辑产生,并且,Mapper的数量很多.-->工厂bean2.扫描mapper包.通过springboot源码包的注解,@MybatisAutoConfiguration 可以看到.通过,各种注解,1.完成sqlSessionfactory的创建.2.每一个mapper,是通过扫描器扫描出来(扫描器继承spring的,然后改过滤器就行了),添加到bdmap中.他们的MapperFactoryBean.bd信息,改成factory类型,需要的参数,也放进去. 某些需要的参数,还利用自动装配(byType,byname)的方式注入进去.比如sqlsessiontemplate.这样,mybatis的数据,就导入到每一个bean中了.直接通过getObject,就可以获取对象.
3.4.2 可以学习的思路

1.MapperFactoryBean的构建思路.->factoryBean 的应用.

3.5 feign 与 Spring 集成.

功能: 从feign的功能上看.他完成了调用端的负载均衡.以及结合了hystrix等功能. 说白了,就是被代理了. 那么这个bean,如何加载到spring容器中,如何完成代理了呢??思路1: 如何需要完成代理,可以想到aop功能,仿造@Transactional的方式, 添加一个advisor,配置好切点.feign数据,通过一个类似事务管理器的东西保存.   pointcut 的匹配功能,还得准备匹配缓存,匹配方法,匹配路径,好麻烦. 工程量太大配置一个扫描器,将bd扫描进spring容器.思路2: 使用factoryBean的方式,工厂bean的方式,创建bean. 工厂bean可以在getObject中,完美用自己的构建方式.   需要自定义的配置一个扫描器,扫描出来bd. 这样改动量最小.类似 Mybatis 的整合方式.

3.6 SpringMVC 源码

功能: 把web应用服务器封装的Servlet,转化为spring可以使用的"reqiest对象"  springmvc,解决了:HandlerMappingHandlerAdapterHandlerExceptionResolver	ViewResolverLocaleResolver, LocaleContextResolverMultipartResolver 在我理解,就是一个服务框架,完成各种功能,将servlet,处理的httpRequest 对象 给用户使用.如何和spring容器整合? 如何扫描的controller数据,封装成合适的map?

3.7 Tomcat 与 Spring

tomcat功能:  通过看 startup.bat 文件,还有启动的main方法,大概了解他的初始化过程,他的主要目的是,获得计算机某个端口的监听权.   当端口有http请求访问的时候,将信息,转化为,java程序可以用的servlet.==>springboot如何和这部分整合?  ==>tomcat中,哪些设计可以学?==>tomcat,解决了哪些问题?用了什么方法?线程池处理请求

1585123457729

3.8 FactoryBean

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值