bean
单例bean的加载模式有立即加载和懒加载两种
单例bean的创建是线程安全的,但是有状态的单例bean本身不是线程安全的
bean的生命周期可以归纳为在初始化方法的前后分别执行后处理器的before和after方法。初始化方法包括@PostConstruct注解,initializingBean接口以及@Bean指定方法三种
后处理器接口包括BeanPostProcessor以及BeanFactoryPostProcessor两类,前者增强bean如提供解析bean的注解@Autowired注解而后者增强bean工厂即自定义修改或增加beanDefinition
DI
bean定义注册时可以通过component以及configuration注解实现,配合@bean注解时,component注入的bean不是单例的而configuration注入的bean是单例的
bean有属性,get方法以及构造器三种注入方式,推荐使用构造器方式,可以注入final对象
获取bean的方式包括Autowired注解默认byType以及Resource注解默认Byname,byType时如果存在多个可以通过@Qualifier或primary注解指明
Autowired注解底层是一个InjectionMetadata对象,在该对象中调用了bean工厂的doResolveDependency()方法获取被当前bean所依赖的bean,即根据Type找到所有bean,如果有多个则依次判断@Qualifier以及@Primary注解
beanFactory主要提供了bean定义的注册以及bean的获取功能,比如在BeanPostProcessor中利用InjectionMetadata对象解析Autowired注解
applicationContext的重点在refresh方法,该方法分为三个节点,准备环境,准备beanFactory以及准备applicationContext
准备beanFactory包括bean定义注册,执行bean工厂后处理器以及准备bean后处理器三部分
准备applicationContext包括事件监听以及发布器注册以及对立即加载的单例bean走一套生命周期流程。此外还有一个onRefresh的扩展点,比如springboot在这里创建tomcat
AOP
aop可以通过aspectJ以及springAOP实现,aspectJ提供了定义切面的注解以及编译和类加载的织入,而springAOP提供了动态代理的织入方式
aspectJ的通知after和afterReturning区别在于afterReturning可以得到切入方法的返回值
aspectJ的类加载以及编译时织入可以实现静态方法的代理以及同对象方法调用的增强,而springAOP不行
springAOP的通知接口为Advice,典型实现就是CGLIB的methodInterceptor对象。
springAOP通过后处理器将aspectJ的@Aspect注解转化为advisor切面对象,而ProxyFactory代理工厂类通过jdk或者cglib动态代理实现advisor切面的功能
事务
事务默认只回滚运行时异常以及error
支持声明式事务以及编程式事务。
声明式事务即通过enable注解注入两个bean,一个切面advisor通知是transactionInterceptor拦截器切点是对@Transaction注解的匹配,一个代理bean通过AOP实现该advisor。编程式事务即通过transactionTemplate对象操作事务
事务拦截器底层通过transactionManager事务管理器管理事务
事务管理器采用模板方法管理事务,具体事务由子类实现,该方法返回一个transactionStatus事务状态对象以提供提交回滚功能
transactionDefinition提供事务属性以启动事务,事务开始后通过transactionStatus对象表示这个事务的状态。事务属性即传播行为,隔离级别以及超时时间等
由于声明式事务基于AOP,所以会在非public方法以及对象内部调用时失效,此外如果通过aop代理a调用事务,因为事务aop优先级高于普通aop,如果a中吞掉了异常,那么事务不会回滚
常用注解
lazy注解作用于bean注解时可以实现懒加载,作用于Autowired注解时可以实现懒解析以解决循环依赖问题
循环依赖
循环依赖更多的是设计问题,如果是构造器注入则需要通过懒解析解决,如果是非构造器注入则spring自己通过三级缓存解决,三级缓存即一级缓存存放最终的单例bean,二级缓存存放代理bean或未初始化的bean,三级缓存存放ObjectFactory对象包含代理配置信息以创建代理
springMVC
执行流程包括三个阶段即初始化阶段初始化dispatcherServlet的几大组件,匹配阶段遍历handlerMapping找到与请求匹配的handlerMethod处理器和handlerAdapter适配器,执行阶段通过适配器调用处理器,处理器包含了controller控制器bean
tomcat包括connector以及container即servlet两部分,connector中使用事件驱动模式处理http,线程池大小为200,并且线程池设计为优先使用救急线程而非任务队列
拦截器是spring组件,基于AOP即handlerInterceptor接口
过滤器是javaEE组件,相比拦截器更加底层,过滤器调用在拦截器外面,并且过滤器是责任链模式需要手动调用,而拦截器spring在dispatchServlet中通过for循环自己调用
监听器主要用于监听bean的启动初始化等事件,不止用于web请求
springboot
启动过程包括springApplication对象的构造以及run方法。主要包括推断应用类型如servlet或reactive以及在run方法中调用applicationContext的refresh方法
springboot的自动配置即starter,通过@EnableXXX注解实现,底层是SPI机制,springSPI的文件名称为spring.factories
@EnableXXX注解底层是@Import注解,该注解用于注入非启动类路径下的bean,该注解配合ImportSelector导入选择器以及springSPI实现类的自动注入
springboot不允许bean覆盖,可以通过延迟导入选择器以及条件装配实现自定义bean覆盖第三方bean
如果需要自定义自动配置可以通过springboot自带的@EnableAutoConfiguration注解该注解内部是@Import注解那一套,并在SPI文件中配置EnableAutoConfiguration接口的实现类实现
AOP的自动配置则是通过在导入选择器中导入配置类,并在该配置类中通过条件装配注入基于jdk或cglib的自动代理创建器
条件装配即通过@Conditional注解搭配Condition接口实现类注入的条件判断
mybatis
底层原理包括三个类,mappedStatement对象封装mapper接口方法中的sql信息,sqlSession提供crud的api,Execute对象真正执行sql,该对象封装了jdbc的ps对象,execute对象对查询结果进行了缓存
通过注册Interceptor拦截器可以实现sql修改以及性能监控,拦截时指明拦截的接口方法,mybatis支持sql执行,入参,以及结果处接口的拦截
#{}与{}是字符串替换,而#{}参数通过ps对象的方法设置
mapper接口基于jdk动态代理,mapperProxy对象是代理的invocationHandler对象,对接口方法进行增强,mapperProxy内部会为每个接口方法构造method对象,该method对象通过sqlSession执行sql
spring通过bean工厂后置处理器以及beanDefinitionScan扫描@MapperScan的包以添加mybatis接口的bean定义,底层是利用了FactoryBean包装mapperProxy对象以构造bean定义