WEB框架之Spring分析

一.IOC


1.1 Autowired和Autowired注解

  • 使用@Autowired注解先按照类型找,再按照属性名字去找,可以配合@Qualifier设置名称去查找;
  • 使用@Resource注解先按name进行查找,然后用类型查找,可以指定name和type属性;

1.2FactoryBean和BeanFactory

  • BeanFactory用于管理bean,是所有容器最基本的形式,比如ApplicationContext对基础容器进行了一层扩展;
  • FactoryBean实际上是一个bean属于BeanFactory可以通过getObject方法用来创建对象,字符串前面加上"&"那么可以返回FactoryBean对象;

扩展:可以通过实现FactoryBean接口定制实例化 bean 的逻辑;

1.3BeanFactory的继承体系

  • BeanFactory(接口) --  ListableBeanFactory(接口)+HierarchicalBeanFactory(接口)+部分子接口  --   ApplicationContext(接口)   --  ConfigurableApplicationContext(接口)
  • AbstractApplicationContext(抽象类)  主要实现类
  • AnnotationConfigApplicationContext+ClassPathXmlApplicationContext(子类基于注解和xml的)

1.4AnnotationConfigApplicationContext

  • 初始化AnnotatedBeanDefinitionReader,#初始化类时注册APP主类的BeanDefinition
  • 初始化ClassPathBeanDefinitionScanner,#用来扫描指定路径下的注解并将BeanDefinition进行注册

ps:如果是传参构造方法会进行注册#register,并且refresh刷新;如果不传参需要自己进行注册#register和刷新#refresh;

注册类的方式

~上下文的registry方法(无法参与BeanDefinition的设置);

~Import导入实现接口ImportBeanDefinitionRegistrar的类(可以参与BeanDefinition的设置);

~Import导入实现接口ImportSelector的类,方法返回需要注册类的数组;(无法参与BeanDefinition的设置);

~Import导入你要注入的类;(无法参与BeanDefinition的设置)

~实现BeanDefinitionRegistryPostProcessor接口类的postProcessorBeanDefinitionRegistry回调方法来注册,另一个方法为空实现即可;(可以参与BeanDefinition的设置

~实现FactoryBean接口的getObject 和 getObjectType方法;(无法参与BeanDefinition的设置)

~使用@Compon直接 和 配置类中使用@Bean注解;(无法参与BeanDefinition的设置)

Import可导入的三种类:自定义的普通类,ImportSelector的实现类(用于指定需要注册为bean的Class名称),ImportBeanDefinitionRegistrar的实现类;

1.5 refresh

  • 1.prepareRefresh(初始化环境变量的信息);
  • 2.obtainFreshBeanFactory,创建beanFactory,解析配置信息(初始配置的xml文件 或者 App的启动类);
  • 3.prepaerBeanFactory,设置属性,添加Bean的后置处理器,注册依赖组件信息;
  • 4.postProcessBeanFactory,执行BeanFactory的后置处理器(空方法,可以进行扩展实现);
  • 5.invokeBeanFactoryPostProcessors,进一步解析BD。
  • 回调实现BeanFactoryPostProcessor接口的类(比如spring内置的ConfigurationClassPostProcessor核心类,会解析Configuration类)
  • 回调实现BeanDefinitionRegistryPostProcessor接口的方法(比如spring内置的ConfigurationClassPostProcessor);

  • 解析过程:先解析出PropertySource,ComponentScan,Import(会处理三种类),ImportResource(导入xml文件),Bean(方法),然后在进行注册解析出来的BD
  • 6.registerBeanPostProcessors,注册BeanPostProcessor接口的实现类;
  • 7.finishBeanFactoryInitialization,实例化非懒加载单例的bean并将对象缓存下来,构造器创建实例---属性注入---初始化之前的拦截器回调---初始化---初始化之后的拦截器回调,bean实例创建好再决定返回bean还是object

ps:AOP的原理,通过EnableAspectJAutoProxy注解导入AspectJAutoProxyRegistrar类,通过该类注册后置处理器BeanPostProcessor,然后在初始化之后的回调方法,获取通知 和 target类 进行生成代理类,而不是原生类;

Bean的生命周期过程:

  • bean的实例化,Supplier 回调方式---factoryMethod工厂方法 --有参构造方法自动注入---无参/默认构造方法,会先对所有的构造方法排序,按照访问权限public和非public 和 参数个数(逆序)来排序,然后循环依次匹配,得到构造方法后会通过反射进行实例化;

扩展:工厂方法初始化和构造函数自动注入初始化两种方式最为复杂,主要是因为构造函数和构造参数的不确定性;

  • bean进行循环依赖的处理;
  • bean在实例化之后有一个后置处理InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation;
  • bean的依赖注入,根据属性名和类型加载bean,然后判断类型转化(因为获取到的是Object类型)在统一进行注入;
  • bean在注入之后有一个后置处理InstantiationAwareBeanPostProcessor#postProcessProperties;
  • bean进行初始化,执行初始化方法,然后执行自定义的init-method,跟属性注入一样会有前后的拦截器 ;

扩展:初始化时,会先判断aware接口,就是在依赖注入之后才进行的;

  • bean初始化完成后,在getObjectForBeanInstance方法中需要判断返回bean的实例是否是FactoryBean;
  • bean的使用完成之后进行销毁,执行销毁前的回调方法,然后执行自定义的destroy-method;

bean的循环依赖问题:

  • A先进行依赖注入(A已经通过反射实例化完成,然后放入三级缓存)会先要初始化完成B,B依赖注入的时候还需要获取A对象会从三级缓存在去获取对象并且放入二级缓存(解决了循环依赖),然后B初始化成功在放入一级缓存,返回A那么A就可以初始化成功在放入一级缓存;
  • ~singletonFactories 三级缓存存放ObjectFactory ,在bean 构造器创建好实例并且初始化之前 缓存起来 ;
  • ~earlySingletonObjects 二级缓存存放 未经过初始化(属性注入 和 init)的对象;
  • ~singletonObjects 一级缓存存放 经过初始化(属性注入 和 init)的对象;
  • 
    public interface ObjectFactory<T> {
        T getObject() throws BeansException;
    }
  • 只能解决setter循环依赖的问题,无法解决构造器循环依赖的问题,因为需要缓存的对象已经进行实例化了(需要调用构造函数的),并且都需要是单例bean

1.6 常用接口介绍

  • BeanPostProcessor:插手bean实例化过程,实例化之后,(初始化前后的回调方法)容器管理实例之前执行;(每一个该接口的实现类都会对所有的Bean进行处理
  • 扩展:AOP动态代理Bean就是在初始化之后的回调方法里进行实现的;
  • InstantiationAwareBeanPostProcessor:BeanPostProcessor的子接口,可以在bean的实例化后,populateBean属性注入时,进行调用;
  • InitializingBean:进行初始化Bean实例,方法afterPropertiesSet在属性注入之后进行执行;
  • BeanFactoryPostProcessor:在单例Bean实例化之前,BeanFactory初始化之后,其主要作用是对加载 BeanDefinition 进行修改。
  • 扩展:实现类ConfigurationClassPostProcessor的回调方法给 加了 @Configuration 的appconfig类加上cglib代理来管理bean;
  • BeanDefinitionRegistryPostProcessor:是BeanFactoryPostProcessor的子类,实现类ConfigurationClassPostProcessor的回调方法,先解析出注解的类,然后在实际进行注册BD
  • ImportSelector:回调方法返回一组类名,并自动把它变为BD不能自己操作BD;
  • ImportBeanDefinitionRegistrar:如果需要自己操作BD可以使用该接口的回调方法;
  • ImportAware:setImportMetadata回调方法 将注解的元信息进行设置;

二.AOP


2.1AOP介绍

  • 面向切面编程,通过动态代理来进行实现,只需要定义好增强方法 和 要被增强的方法,配置切点、通知和切面,然后就可以生成动态代理类来进行方法增强,避免了OOP面向对象编程的继承或者实现一个接口增加的代码之间的耦合性以及冗余代码量。

2.2概念

  • Aspect:切面,切入系统的一个切面 、组合了 Pointcut 与 Advice,可以是一个切点对应多个通知 ;
  • Advisor:类似于切面,也是组合了 Pointcut 与 Advice,只能是一个切点对应一个通知 ;
  • 扩展:切面只是一个概念,并没有一个具体的接口或类与此对应,spring使用PointcutAdvisor来进行了代替;
  • Join point:连接点,指代一个个被代理的方法
  • Point cut:切入点,用来匹配连接点 (可以包含多个连接点)、确定在哪些连接点(Join point)处应用通知、
  • Advice:通知, 作用于连接点行为实现 、
  • Before advice : 前置通知 、
  • After returning advice : 后置通知 (在方法正常结束之后执行的代码,可以访问到方法的返回值)、
  • After throwing advice : 异常通知 、
  • After (finally) advice : 后置通知(方法执行之后,不管是否发生异常,不能访问目标方法的返回结果) 、
  • Around advice : 环绕通知(等价于前置、两个后置以及异常通知)、

SpringAOP 前置通知、后置通知 - 惶者 - 博客园

  • Target Object:目标对象,被一个或者多个切面通知的对象 、
  • AOP proxy:AOP代理,JDK或者CGLIB

2.3AOP 实际过程

  • 初始化通知器链advisor,比如从xml里解析出来的、
  • 实际通过 JdkDynamicAopProxy / CglibAopProxy  来创建代理对象 、(需要传参,类加载器,接口,通知器=Advise + PointCut)  、
  • 根据连接器链去初始化拦截器链,调用proceed方法实际会调用拦截器链、
  • 实际会调用拦截器的invoke方法,通过调用拦截器链里的advice通知对joinpoint目标方法增强,核心就是利用回调

2.4AOP的应用

  • 比如事务机制就是通过AOP生成代理类来进行实现的;
  • 扩展:事务的传播方式有三种;
  • 扩展:事务的回滚策略,编译时/受检查异常不会回滚;
  • 扩展:事务开启多线程后无效原因,spring中用threadlocal存储数据库连接,代表一个线程对应一个连接然后对应一个事务,如果多线程那么就会有多个事务,肯定会失效的;

三.MVC


3.1概念

  • view层自身为组合模式;
  • controller层与view为策略模式controller为算法的实现而view为策略的组合;
  • mode层和view为监听者模式model实现自身的回调方法在view中进行注册当view发生变化就会通知回调model进行处理;

拦截器和过滤器:都是通过AOP技术给方法进行增强,过滤器属于servlet里的,拦截器基于springMVC(更加常用);

3.2初始化ApplicationContext

  • 在 web.xml 配置ContextLoaderListener监听器;
  • 接听到事件会通过反射class.forname进行创建springweb容器并refresh刷新容器

3.3初始化DispatcherServlet

  • DispatcherServlet的父类HttpServletBean实现了init方法;
  • 获取springweb容器(如果没有会先创建在refresh刷新容器最终通过DispatcherServlet的initStrategies方法对八大组件进行初始化;

ps:初始化默认加载的类是DispacterServlet通过静态代码块加载DispacterServlet.properties文件里的类,用反射来生成的。

3.4处理请求

  • 1.DispacterServlet(实现一个servlet拦截所有请求,在统一进行分发处理)的doService方法

2.根据处理器映射器,从三种处理器中获取到对应的handler;

  • RequestMappingHandlerMapping,这个映射器主要是在Controller类中配置@RequestMapping注解(一般使用这个);
  • BeanNameUrlHandlerMapping,根据bean的name去寻找hanler;

  • SimpleUrlHandlerMapping,这个映射器的规则是,让DispatchServlet去找bean的id与URL相对应的handler;

 Springmvc 的HandlerMapping(处理器映射器)_m0_38120426的博客-CSDN博客

3.通过处理器,从三种适配器获取到对应的适配器;

  • RequestMappingHandlerAdapter,一种基于@Controller注解配置的;
  • SimpleControllertHandlerAdapter,一种实现Controller接口;
  • HttpRequestHandlerAdapter,一种实现HttpRequestHandler接口;
  • 4.调用用户自定义的拦截器链;
  • 5.适配器调用我们实现的handler,先进行参数解析(根据方法参数跟request里的参数进行对应),在通过反射来进行实际的调用,最终经过value解析器得到ModelAndView结果;
  • 6.将ModelAndView结果进行视图解析,并且进行渲染;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值