转载

Spring 知识框架

没有IOC 之前:我们需要一个对象,都是我们自己去new 一个依赖对象。 有了IOC 之后: 我们将创建对象的权益交给了IOC 容器,由容器来控制对象的创建和生命周期。对象只是被动的接受依赖对象。

为什么需要IOC?IOC 的好处?

控制反转其实是一种设计思想。没有控制反转,我们需要一个对象,我们就自己去NEW ,导致代码之间的高度耦合。有了控制反转,由容器来控制对象的依赖注入,代码之间松散耦合。

参考: blog.csdn.net/qq_42709262…

IOC 源码跟读

IOC 和DI 主要是通过反射机制完成的。

@Override
public void refresh() throws BeansException, IllegalStateException {
   // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
   synchronized (this.startupShutdownMonitor) {

      // 准备工作
      // 1、记录下容器的启动时间
      // 2、标记“已启动”状态
      // 3、处理配置文件中的占位符
      prepareRefresh();

      // 生成BeanFactory
      // 1、生成 BeanFactory
      // 2、解析配置文件,生成BeanDefinition, 注册到BeanFactory
      // 此时,Bean 还未初始化,只是配置信息提取出来了。BeanDefinition 的保存格式
      // beanName-> beanDefinition 的 map
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 1、设置 BeanFactory 的类加载器,用于BeanFactory 加载类;
      // 2、添加一个 BeanPostProcessor
      // 3、对ApplicationContext 继承的对象进行赋值
      // 4、手动注册几个特殊的 bean,如environment、systemProperties、systemEnvironment
      // 这块待会会展开说
      prepareBeanFactory(beanFactory);

      try {
         // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
         // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】

         // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
         // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
         postProcessBeanFactory(beanFactory);
         // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
         invokeBeanFactoryPostProcessors(beanFactory);          

         // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
         registerBeanPostProcessors(beanFactory);

         // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
         initMessageSource();

         // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
         initApplicationEventMulticaster();

         // 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
         // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
         registerListeners();

         // 重点,重点,重点
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // 最后,广播事件,ApplicationContext 初始化完成,不展开
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // 把异常往外抛
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
复制代码

参考: yikun.github.io/2015/05/29/… javadoop.com/post/spring…

Bean 的生命周期

加载XML——创建BeanFactory ——读取Resource —— 解析BeanDefinition ——注册到BeanFactory ——初始化Bean ——创建Bean 实例 —— 注入Property

AOP

静态代理、JDK动态代理、CGLIB动态代理。

静态代理:代理类实现被代理类的接口,同时与被代理类是组合关系。 JDK动态代理:代理类可代理任意类的任意方法,但是,任意类必须要实现某个接口。 CGLIB动态代理:CGlib是一个字节码增强库,为AOP等提供了底层支持。

AOP:即面向切面编程,AOP可以分离系统的业务逻辑和系统服务。

参考: www.cnblogs.com/puyangsky/p… juejin.im/post/5aa781…

Spring单例与线程安全

懒加载:spring 默认的是非懒加载,即在容器初始化时候初始化;懒加载即用户向容器第一次索要bean时进行初始化。

spring依赖注入时,使用了双重判断加锁的单例模式。首先从缓存中获取bean实例,如果为null,对缓存map加锁,然后再从缓存中获取bean,如果继续为null,就创建一个bean。这样双重判断,能够避免在加锁的瞬间,有其他依赖注入引发bean实例的创建,从而造成重复创建的结果。

参考: www.cnblogs.com/chengxuyuan…

Spring事务管理

事务隔离级别:

TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别. TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读 TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生 TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。 TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

事务传播行为:

支持当前事务的情况:

TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。 TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不支持当前事务的情况:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。

其他情况:

TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

实现声明式事务的四种方式:

1、基于 TransactionInterceptor 的声明式事务: Spring 声明式事务的基础,通常也不建议使用这种方式,但是与前面一样,了解这种方式对理解 Spring 声明式事务有很大作用。

2、基于 TransactionProxyFactoryBean 的声明式事务: 第一种方式的改进版本,简化的配置文件的书写,这是 Spring 早期推荐的声明式事务管理方式,但是在 Spring 2.0 中已经不推荐了。

3、基于< tx> 和< aop>命名空间的声明式事务管理: 目前推荐的方式,其最大特点是与 Spring AOP 结合紧密,可以充分利用切点表达式的强大支持,使得管理事务更加灵活。

4、基于 @Transactional 的全注解方式: 将声明式事务管理简化到了极致。开发人员只需在配置文件中加上一行启用相关后处理 Bean 的配置,然后在需要实施事务管理的方法或者类上使用 @Transactional 指定事务规则即可实现事务管理,而且功能也不必其他方式逊色。

参考: juejin.im/post/5b010f…

原文  https://juejin.im/post/5dedb3aae51d455821124f79
正文到此结束
Loading...