依赖倒置原则: 依赖倒置的核心是面向接口编程

  1. 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
  2. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
  3. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

控制反转(Inversion of Control):

是依赖倒置原则的一种代码设计的思路。具体采用的方法就是所谓的依赖注入(Dependency Injection)。

IoC Contain:

  1. 避免写大量的new来创建对象,将对象间的依赖关系,配置化。
  2. 创建实例的时候不需要了解具体的细节。

Spring Bean生产总体流程:

Spring 是一个大的 Bean 工厂,创建Bean时要考虑如下问题:

  1. Bean定义。根据配置文件或者注解加载Bean定义到BeanDefinitionMap。
  2. 作用域。单例作用域或者原型作用域,单例的话需要全局实例化一次,原型每次创建都需要重新实例化。
  3. 依赖关系。一个 Bean 如果有依赖,我们需要初始化依赖,然后进行关联。如果多个 Bean 之间存在着循环依赖,A 依赖 B,B 依赖 C,C 又依赖 A,需要解这种循环依赖问题。

Bean 定义:

  1. 基于XML

    <bean id="userService" class="com.javhl.***.UserService" init-method="init" destory-method="destory"/>
    
  2. 基于注解

    @Component:当对组件的层次难以定位的时候使用这个注解
    @Controller:表示控制层的组件
    @Service:表示业务逻辑层的组件
    @Repository:表示数据访问层的组件
    
  3. 基于JavaConfig

    @Configuration
    public class JavaConfigBeanTest {@Beanpublic BeanTest beanTest(){BeanTest beanTest = new BeanTest();beanTest.setTestField("I am a beanTest");return beanTest;}
    }
    

作用域:

循环依赖问题:

  1. 循环依赖根据注入方式分成两种类型:

    1. 构造器循环依赖。依赖的对象是通过构造器传入的,发生在实例化 Bean 的时候。
    2. 设值循环依赖。依赖的对象是通过 setter 方法传入的,对象已经实例化,发生属性填充和依赖注入的时候。
    3. 如果是构造器循环依赖,本质上是无法解决的。比如我们调用 A 的构造器,发现依赖 B,于是去调用 B 的构造器进行实例化,发现又依赖 C,于是调用 C 的构造器去初始化,结果依赖 A,整个形成一个死结, 导致 A 无法创建。如:A { public A(B b){}};B{public B(A a){}},A,B实例化时形成构造器循环依赖
    4. 如果是设值循环依赖,Spring框架只支持单例下的设值循环依赖。Spring 通过对还在创建过程中的单例,缓存并提前暴露该单例,使得其他实例可以引用该依赖。
  2. 原型模式和单例构造器循环依赖问题:

    1. 加载 A,记录 singletonsCurrentlyInCreation = [a],构造依赖 B,开始加载 B。
    2. 加载 B,记录 singletonsCurrentlyInCreation = [a, b],构造依赖 C,开始加载 C。
    3. 加载 C,记录 singletonsCurrentlyInCreation = [a, b, c],构造依赖 A,又开始加载 A
    4. 加载 A,检测到循环依赖,直接抛出异常结束操作
  3. 单例setter循环依赖解决方法:

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {// 查询缓存中是否有创建好的单例Object singletonObject = this.singletonObjects.get(beanName);// 如果缓存不存在,判断是否正在创建中if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {// 加锁防止并发synchronized (this.singletonObjects) {// 从earlySingletonObjects中查询是否有early缓存singletonObject = this.earlySingletonObjects.get(beanName);// early缓存也不存在,且允许early引用if (singletonObject == null && allowEarlyReference) {// 从单例工厂Map里查询beanNameObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// singletonFactory存在,则调用getObject方法拿到单例对象singletonObject = singletonFactory.getObject();// 将单例对象添加到early缓存中this.earlySingletonObjects.put(beanName, singletonObject);// 移除单例工厂中对应的singletonFactorythis.singletonFactories.remove(beanName);}}}}return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
    
    1. 采用三级缓存
    2. singletonObjects(一级缓存),单例缓存,存储已经实例化完成的单例,成品的Bean。
    3. earlySingletonObjects(二级缓存),提前暴露的单例缓存,这时候的单例刚刚创建完,后期还会注入依赖,存放半成品的Bean。
    4. singletonFactories(三级缓存),生产单例的工厂的缓存,存的是Bean工厂对象,用来生成半成品的Bean并放入到二级缓存中。用以解决循环依赖。如果Bean存在AOP的话,返回的是AOP的代理对象。为了解决二级缓存中 AOP 生成新对象的问题,Spring 中的解决方案就是提前 AOP。
    5. 从流程图上看,实际上注入 C的 A 实例,还在填充属性阶段,并没有完全地初始化。等递归回溯回去,A 顺利拿到依赖 B,才会真实地完成 A 的加载。

BeanFactory & FactoryBean:

  1. BeanFactory: 以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系。
  2. FactoryBean: 一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean的形式
  3. 以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";Object getBean(String var1) throws BeansException;<T> T getBean(String var1, Class<T> var2) throws BeansException;Object getBean(String var1, Object... var2) throws BeansException;<T> T getBean(Class<T> var1) throws BeansException;<T> T getBean(Class<T> var1, Object... var2) throws BeansException;boolean containsBean(String var1);boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;Class<?> getType(String var1) throws NoSuchBeanDefinitionException;String[] getAliases(String var1);
}public interface FactoryBean<T> {T getObject() throws Exception;Class<?> getObjectType(); boolean isSingleton();
} 
//FactoryBean实例
@Component public class FactoryBeanTest implements FactoryBean{private String type=”a”; @Overridepublic Object getObject() throws Exception { if("a".equals(type)){ return new A(); }else{return new B(); } }@Override public Class getObjectType() { if("a".equals(type)){ return A.class; }else{return B.class; } }@Override public boolean isSingleton() { return true; }
}ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testBeans.xml");
String[] names = applicationContext.getBeanDefinitionNames();
Arrays.stream(names).forEach(e->System.out.println(e));
//此处获取的是类A的实例
Object realBean = applicationContext.getBean("factoryBeanTest");
System.out.println(realBean.getClass().getName());
//此处获取的是FactoryBeanTest的实例
FactoryBeanTest factoryBeanTest = (FactoryBeanTest)
applicationContext.getBean("&factoryBeanTest");
((ClassPathXmlApplicationContext) applicationContext).close();

Spring技术原理之Spring IOC相关推荐

  1. Spring技术原理之Spring AOP

    静态代理: 问题: 每个RealSubject对应编写一个Proxy类,比较麻烦. 大量的Proxy类会导致类规模增大不易维护,影响编译 动态代理: 两个问题: 自动生成的Proxy类如何代理实体类? ...

  2. 【深入浅出Spring原理及实战】「技术原理」Spring Security的核心功能和加载运行流程的原理分析

    SpringSecurity的架构总览 Spring Security的简介说明 Spring Security对认证.授权和常见漏洞保护提供了全方位支持.使用的版本为:Spring Security ...

  3. modelandview使用过程_面试问烂的 Spring AOP 原理、Spring MVC 过程

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者:莫那一鲁道链接:www.jianshu.com/p/e18fd44964eb Spring AOP ,SpringMVC ,这两个应该 ...

  4. Spring技术原理之Bean生命周期

    生命周期图解 生命周期举例 public class BeanLifeTest implements BeanNameAware, ApplicationContextAware, Initializ ...

  5. Spring AOP原理解析——Spring事务

    Spring申明式事务有两种方式: 基于配置文件 基于注解 一.基于配置文件的事务 <!-- 会重复读,不会脏读事务 --> <tx:advice id="defaultT ...

  6. 一步一步手绘Spring MVC运行时序图(Spring MVC原理)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  7. Spring工作原理与单例ThreadLocal

    最近看到spring管理的bean为单例的,当它与web容器整合的时候始终搞不太清除,就网上搜索写资料, Tomcat与多线程 servlet是多线程执行的,多线程是容器提供的能力. servlet为 ...

  8. Spring事务原理-1-transactionManager以及Connection的本质

    Spring事务原理 1.spring事务配置 2.Connection本质的探究 3. Spring事务的底层原理 1.spring事务配置 <bean id="transactio ...

  9. springaop事务逻辑原理_太狠了!阿里大牛手写的Spring核心面试笔记:IOC+AOP+MVC+事务...

    Spring作为现在最流行的java 开发技术,其内部源码设计非常优秀.如果你不会Spring,那么很可能面试官会让你回家等通知. Spring是什么? 有一个工地,几百号人在用铁锹铲子挖坑. 如果开 ...

最新文章

  1. python绘制3维图-Python 画出来六维图
  2. linux查看文件夹目录大小
  3. 【Git】搭建Git 服务器
  4. 10丨 Redis主从同步与故障切换,有哪些坑
  5. 字体--Ubuntu手记之系统配置
  6. KDD走进阿里 数百专家聚集探讨产学研一体化
  7. python参数注解
  8. 在32位windows 7下安装PyLucene
  9. Dubbo2.7源码分析-SPI的应用
  10. 【Linux】tee命令
  11. oracle lock 1,Oracle試用 DBMS_LOCK.sleep(1);權限問題
  12. TF400511: Your team has not defined any iterations to use as sprints
  13. android开发项目app实例_JNPF快速开发平台-快速开发Web+APP项目的java开发平台
  14. XenCenter6.2 配置ISO库
  15. C Sharp进行附合水准路线计算中间点高程简易程序
  16. java内嵌浏览器的几种方式
  17. 电脑模拟收银机_机场收银模拟器下载
  18. 《论英语能力从小开始培养的重要性,不一定是非要去国外》
  19. IT自学网有视频教程
  20. 企业数字化转型迫切,团队协同工具何以成为“杀手锏”?

热门文章

  1. oracle 审计结果表,oracle对某表进行审计,观察对这个表的增删改查等sql操作
  2. 前脚投简历,后脚就被精准裁员。这套监控系统让打工人颤抖:离职倾向、摸鱼通通都能被监测,争议出现后产品页面已404...
  3. 【中国好公司】中国人最向往的公司:BAT相差太多!华为排名出乎意料
  4. 成功者十三个价值连城的习惯
  5. 1908元?iPhone SE 3价格大幅下调,网友:这个价格我冲了
  6. 顺丰同城宣布苏炳添出任首位品牌代言人
  7. 腾讯视频已上线超前点播选集解锁
  8. 外媒:苹果正研发新的Apple Watch机型 显示屏和速度将升级
  9. 腾讯公司被法院强制执行25元,刚好是QQ超级会员的价格
  10. 北京市将持续扩大5G网络建设规模 超前布局6G