Spring原理讲解

1、什么是Spring框架-Spring框架主要包含哪些模块

​ Spring是一个开源框架-Spring是一个轻量级的Java 开发框架。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构-分层架构允许使用者选择使用哪一个组件-同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而-Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言-任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说-Spring是一个分层的full-stack(一站式) 轻量级开源框架。

主要包含的模块:

illustration

2、Spring框架的优势

​ 1、Spring通过DI、AOP和消除样板式代码来简化企业级Java开发

​ 2、Spring框架之外还存在一个构建在核心框架之上的庞大生态圈-它将Spring扩展到不同的领域-如Web服务、REST、移动开发以及NoSQL

​ 3、低侵入式设计-代码的污染极低

​ 4、独立于各种应用服务器-基于Spring框架的应用-可以真正实现Write Once,Run Anywhere的承诺

​ 5、Spring的IoC容器降低了业务对象替换的复杂性-提高了组件之间的解耦

​ 6、Spring的AOP允许将一些通用任务如安全、事务、日志等进行集中式处理-从而提供了更好的复用

​ 7、Spring的ORM和DAO提供了与第三方持久层框架的的良好整合-并简化了底层的数据库访问

​ 8、Spring的高度开放性-并不强制应用完全依赖于Spring-开发者可自由选用Spring框架的部分或全部

3、IOC和DI是什么?

​ 控制反转是就是应用本身不负责依赖对象的创建和维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就有应用转移到了外部容器,控制权的转移就是控制反转。

​ 依赖注入是指:在程序运行期间,由外部容器动态地将依赖对象注入到组件中如:一般-通过构造函数注入或者setter注入。

4、描述下Spring IOC容器的初始化过程

​ Spring IOC容器的初始化简单的可以分为三个过程:

​ 第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程-就像水桶装水需要先找到水一样。

​ 第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构-而这个容器内部的数据结构就是BeanDefition。

​ 第三个过程是向IOC容器注册这些BeanDefinition的过程-这个过程就是将前面的BeanDefition保存到HashMap中的过程。

5、BeanFactory 和 FactoryBean的区别?

  • BeanFactory是个Factory-也就是IOC容器或对象工厂-在Spring中-所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的-提供了实例化对象和拿对象的功能。
  • 使用场景: - 从Ioc容器中获取Bean(byName or byType) - 检索Ioc容器中是否包含指定的Bean - 判断Bean是否为单例

  • FactoryBean是个Bean-这个Bean不是简单的Bean-而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
  • 使用场景 - ProxyFactoryBean

    6、BeanFactory和ApplicationContext的异同

    illustration

    相同:

  • Spring提供了两种不同的IOC 容器-一个是BeanFactory-另外一个是ApplicationContext-它们都是Java interface-ApplicationContext继承于BeanFactory(ApplicationContext继承ListableBeanFactory。
  • 它们都可以用来配置XML属性-也支持属性的自动注入。
  • 而ListableBeanFactory继承BeanFactory)-BeanFactory 和 ApplicationContext 都提供了一种方式-使用getBean(“bean name”)获取bean。
  • 不同:

  • 当你调用getBean()方法时-BeanFactory仅实例化bean-而ApplicationContext 在启动容器的时候实例化单例bean-不会等待调用getBean()方法时再实例化。
  • BeanFactory不支持国际化-即i18n-但ApplicationContext提供了对它的支持。
  • BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为监听器的bean。
  • BeanFactory 的一个核心实现是XMLBeanFactory 而ApplicationContext 的一个核心实现是ClassPathXmlApplicationContext-Web容器的环境我们使用WebApplicationContext并且增加了getServletContext 方法。
  • 如果使用自动注入并使用BeanFactory-则需要使用API注册AutoWiredBeanPostProcessor-如果使用ApplicationContext-则可以使用XML进行配置。
  • 简而言之-BeanFactory提供基本的IOC和DI功能-而ApplicationContext提供高级功能-BeanFactory可用于测试和非生产使用-但ApplicationContext是功能更丰富的容器实现-应该优于BeanFactory
  • 7、Spring Bean 的生命周期?

    illustration

    总结:

    (1)实例化Bean:

    对于BeanFactory容器-当客户向容器请求一个尚未初始化的bean时-或初始化bean的时候需要注入另一个尚未初始化的依赖时-容器就会调用createBean进行实例化。对于ApplicationContext容器-当容器启动结束后-通过获取BeanDefinition对象中的信息-实例化所有的bean。

    (2)设置对象属性(依赖注入):

    实例化后的对象被封装在BeanWrapper对象中-紧接着-Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。

    (3)处理Aware接口:

    接着-Spring会检测该对象是否实现了xxxAware接口-并将相关的xxxAware实例注入给Bean:

    ①如果这个Bean已经实现了BeanNameAware接口-会调用它实现的setBeanName(String beanId)方法-此处传递的就是Spring配置文件中Bean的id值;

    ②如果这个Bean已经实现了BeanFactoryAware接口-会调用它实现的setBeanFactory()方法-传递的是Spring工厂自身。

    ③如果这个Bean已经实现了ApplicationContextAware接口-会调用setApplicationContext(ApplicationContext)方法-传入Spring上下文;

    (4)BeanPostProcessor:

    如果想对Bean进行一些自定义的处理-那么可以让Bean实现了BeanPostProcessor接口-那将会调用postProcessBeforeInitialization(Object obj, String s)方法。

    (5)InitializingBean 与 init-method:

    如果Bean在Spring配置文件中配置了 init-method 属性-则会自动调用其配置的初始化方法。

    (6)如果这个Bean实现了BeanPostProcessor接口-将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的-所以可以被应用于内存或缓存技术;

    以上几个步骤完成后-Bean就已经被正确创建了-之后就可以使用这个Bean了。

    (7)DisposableBean:

    当Bean不再需要时-会经过清理阶段-如果Bean实现了DisposableBean这个接口-会调用其实现的destroy()方法;

    (8)destroy-method:

    最后-如果这个Bean的Spring配置中配置了destroy-method属性-会自动调用其配置的销毁方法。

    8、Spring AOP的实现原理?

    ​ Spring AOP使用的动态代理-所谓的动态代理就是说AOP框架不会去修改字节码-而是在内存中临时为方法生成一个AOP对象-这个AOP对象包含了目标对象的全部方法-并且在特定的切点做了增强处理-并回调原对象的方法。

    ​ Spring AOP中的动态代理主要有两种方式-JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类-并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

    ​ 如果目标类没有实现接口-那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library)-是一个代码生成的类库-可以在运行时动态的生成某个类的子类-注意-CGLI