前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring的原理性总结

Spring的原理性总结

作者头像
小勇DW3
发布2018-08-30 09:51:02
3.9K0
发布2018-08-30 09:51:02
举报
文章被收录于专栏:小勇DW3

一、Bean的生命过程

Bean的生命过程可以借鉴Servlet的生命过程,了解其生命过程对于不管是思想还是以后的使用都很有帮助;

Bean可以通过两种方式进行加载,分别是使用BeanFactory 和 applicationContext, 下边就这两种方式进行Bean的声明周期总结:

applicationContext:

先用一种生命周期流程图来概括;

1:Bean的建立:

容器寻找Bean的定义信息并将其实例化,也就是new一个对象,。

2:属性注入:

使用依赖注入,Spring按照Bean定义信息配置Bean所有属性,相当于调用set方法进行属性set操作

3. 如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean的ID

4. 如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身(可以用这个方法获取到其他Bean)

5. 如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比4更好,以为ApplicationContext是BeanFactory的子接口,有更多的实现方法

6. 如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用After方法,也可用于内存或缓存技术

7.如果设置了initializingBean接口,则会调用实现的afterPropertiesSet()方法;

8. 如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法【相当于定制方法】

9. 如果这个Bean关联了BeanPostProcessor接口,将会调用postAfterInitialization(Object obj, String s)方法

注意:以上工作完成以后就可以用这个Bean了,那这个Bean是一个single的,所以一般情况下我们调用同一个ID的Bean会是在内容地址相同的实例

10. 容器关闭,当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroy方法,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法

BeanFactory:

下边对BeanFactory的生命周期过程进行分析,BeanFactory的生命周期相对于ApplicationContext来说相对简化了一些;

下面用图进行概括:

下面以BeanFactory为例,说明一个Bean的生命周期活动

  • Bean的建立, 由BeanFactory读取Bean定义文件,并生成各个实例
  • Setter注入,执行Bean的属性依赖注入
  • BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName方法
  • BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法
  • InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行其afterPropertiesSet()方法
  • Bean定义文件中定义init-method
  • DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法
  • Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

如果使用ApplicationContext来维护一个Bean的生命周期,则基本上与上边的流程相同,只不过在执行BeanNameAware的setBeanName()后,若有Bean类实现了org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,然后再进行BeanPostProcessors的processBeforeInitialization() 实际上,ApplicationContext除了向BeanFactory那样维护容器外,还提供了更加丰富的框架功能,如Bean的消息,事件处理机制等

 结果展示:

二、BeanFactory 接口和 ApplicationContext 接口有什么区别 ?

    ①ApplicationContext 接口继承BeanFactory接口,Spring核心工厂是BeanFactory ,BeanFactory采取延迟加载,第一次getBean时才会初始化Bean, ApplicationContext是会在加载配置文件时初始化Bean。

    ②ApplicationContext是对BeanFactory扩展,它可以进行国际化处理、事件传递和bean自动装配以及各种不同应用层的Context实现 

开发中基本都在使用ApplicationContext, web项目使用WebApplicationContext ,很少用到BeanFactory

代码语言:javascript
复制
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
IHelloService helloService = (IHelloService) beanFactory.getBean("helloService");
helloService.sayHello();

三、Bean的加载方式:

   1)使用类构造器实例化(默认无参数)

代码语言:javascript
复制
 <bean id="bean1" class="cn.itcast.spring.b_instance.Bean1"></bean>

    2)使用静态工厂方法实例化(简单工厂模式)

代码语言:javascript
复制
//下面这段配置的含义:调用Bean2Factory的getBean2方法得到bean2
<bean id="bean2" class="cn.itcast.spring.b_instance.Bean2Factory" factory-method="getBean2"></bean>

    3)使用实例工厂方法实例化(工厂方法模式)

代码语言:javascript
复制
//先创建工厂实例bean3Facory,再通过工厂实例创建目标bean实例
<bean id="bean3Factory" class="cn.itcast.spring.b_instance.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>

四、请介绍一下Spring框架中Bean的生命周期和作用域

(1)bean定义

    在配置文件里面用<bean></bean>来进行定义。

(2)bean初始化

    有两种方式初始化:

A.在配置文件中通过指定init-method属性来完成

B.实现org.springframwork.beans.factory.InitializingBean接口

(3)bean调用

    有三种方式可以得到bean实例,并进行调用

(4)bean销毁

    销毁有两种方式

A.使用配置文件指定的destroy-method属性

B.实现org.springframwork.bean.factory.DisposeableBean接口

##作用域

singleton

当一个bean的作用域为singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。

prototype

Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean() 方法)时都会创建一个新的bean实例。根据经验,对所有有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用 singleton作用域

request

在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用 域仅在基于web的Spring ApplicationContext情形下有效。

session

在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

global session

在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于 web的Spring ApplicationContext情形下有效。

五、Bean注入属性有哪几种方式?

spring支持构造器注入和setter方法注入

    构造器注入,通过 <constructor-arg> 元素完成注入

    setter方法注入, 通过<property> 元素完成注入【开发中常用方式】

六、Spring的核心类有哪些,各有什么作用?

BeanFactory:产生一个新的实例,可以实现单例模式

BeanWrapper:提供统一的get及set方法

ApplicationContext:提供框架的实现,包括BeanFactory的所有功能

七、Spring里面如何配置数据库驱动?

使用”

代码语言:javascript
复制
com.mchange.v2.c3p0.ComboPooledDataSource

”数据源来配置数据库驱动。示例如下:

代码语言:javascript
复制
      <!-- 配置数据库数据源 -->
      <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">      
        <property name="driverClass" value="${jdbc.driverClassName}"/>      
        <property name="jdbcUrl" value="${jdbc.url}"/>      
        <property name="user" value="${jdbc.username}"/>      
        <property name="password" value="${jdbc.password}"/>
               
        <!-- 初始化连接大小 -->
        <property name="initialPoolSize" value="${initialSize}"/>
        <!-- 最小连接池数量 -->
        <property name="minPoolSize" value="${minActive}" />
        <!-- 连接池最大数量 -->
        <property name="maxPoolSize" value="${maxActive}"/>
         <property name="autoCommitOnClose" value="true"/>
    </bean> 

八、Spring里面applicationContext.xml文件能不能改成其他文件名?

ContextLoaderListener是一个ServletContextListener, 它在你的web应用启动的时候初始化。缺省情况下, 它会在WEB-INF/applicationContext.xml文件找Spring的配置。

你可以通过定义一个<context-param>元素名字为”contextConfigLocation”来改变Spring配置文件的 位置。示例如下: 

代码语言:javascript
复制
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener
        <context-param> 
         <param-name>contextConfigLocation</param-name> 
         <param-value>/WEB-INF/xyz.xml</param-value> 
        </context-param>   
    </listener-class> 
</listener> 

九、Spring如何处理线程并发问题?

Spring使用ThreadLocal解决线程安全问题【博客有一节专门对于TreadLocal的分析】

我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。

在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。

而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

十、为什么要有事物传播行为?

十一、介绍一下Spring的事物管理

    事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。

开发中为了避免这种情况一般都会进行事务管理。Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管 理,可以通过Spring的注入来完成此功能。spring提供了几个关于事务处理的类:

TransactionDefinition //事务属性定义

TranscationStatus //代表了当前的事务,可以提交,回滚。

PlatformTransactionManager这个是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类 AbstractPlatformTransactionManager,我们使用的事务管理类例如 DataSourceTransactionManager等都是这个类的子类。

一般事务定义步骤:

代码语言:javascript
复制
TransactionDefinition td =newTransactionDefinition();
TransactionStatus ts = transactionManager.getTransaction(td);
try{ 
    //do sth
    transactionManager.commit(ts);
}catch(Exception e){
    transactionManager.rollback(ts);
}

 spring提供的事务管理可以分为两类:编程式的和声明式的。

编程式的,比较灵活,但是代码量大,存在重复的代码比较多;

编程式主要使用transactionTemplate。省略了部分的提交,回滚,一系列的事务对象定义,需注入事务管理对象.【这里使用了模板模式】

代码语言:javascript
复制
void add(){
    transactionTemplate.execute(newTransactionCallback(){
        pulic Object doInTransaction(TransactionStatus ts){
         //do sth
        }
    }
}

声明式:声明式的比编程式的更灵活。

使用TransactionProxyFactoryBean:PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED,readOnly

围绕Poxy的动态代理 能够自动的提交和回滚事务

org.springframework.transaction.interceptor.TransactionProxyFactoryBean

PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED–如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与 PROPAGATION_REQUIRED类似的操作。

十二、AOP

1. 说出Spring的通知类型有哪些?

spring共提供了五种类型的通知:

通知类型

接口

描述

Around 环绕通知

org.aopalliance.intercept.MethodInterceptor

拦截对目标方法调用

Before 前置通知

org.springframework.aop.MethodBeforeAdvice

在目标方法调用前调用

After  后置通知

org.springframework.aop.AfterReturningAdvice

在目标方法调用后调用

Throws 异常通知

org.springframework.aop.ThrowsAdvice

当目标方法抛出异常时调用

代码语言:javascript
复制
<bean id="myMethodBeforeAdvice" class="com.cdtax.aop.MyMethodBeforeAdvice"></bean>
<!-- 配置后置通知 -->
<bean id="myAfterReturningAdvice" class="com.cdtax.aop.MyAfterReturningAdvice"></bean>
<!-- 配置代理对象 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> 
<!-- 代理接口集 -->
    <property name="proxyInterfaces">
        <list>
            <value>com.cdtax.aop.TestServiceInter</value>
            <value>com.cdtax.aop.TestServiceInter2</value>
        </list>
    </property>
    
    <!-- 把通知织入到代理对象  | 拦截器名集-->
    <property name="interceptorNames">
        <list>
        <!-- 相当于把 MyMethodBeforeAdvice前置通知和代理对象关联起来,我们也可以把通知看成拦截器,struts2核心就是拦截器 -->
         <value>myMethodBeforeAdvice</value> 
                
        <!-- 织入后置通知 -->
        <value>myAfterReturningAdvice</value>
                
        </list>
    </property>
    
    <!-- 配置被代理对象,可以指定 -->
    <property name="target" ref="test1Service">
        
    </property>
</bean>
</beans>

2. 谈谈目标对象实现接口与目标对象不实现接口有什么区别?

3. 请描述JDK动态代理和CGLI代理的区别?

  jdk动态代理是目标类实现了接口,而不能针对类;

  CGLI动态代理是目标类没有实现接口。主要是对指定的类生成一个子类,覆盖其中的方法。

4. 简述ProxyFactoryBean的作用是什么?

5. 叙述Spring中的自动代理的原理?

5. 写出创建代理对象需指定的三要素是什么?

 (1)设定目标对象  (2)设定代理接口  (3)设定拦截器的名字

6. 写出代理的两种方式分别是什么?

7. 请简述:什么是AOP?简述AOP核心?

9. 请叙述AOP事务的含义?

1. 请简述Spring的工作机制?

2. 请回答你为什么用Spring的工作机制?

3. 请简述Spring是什么?

4. 简述spring的组成?

5.简述Spring容器提供了哪些功能?

6. 在Spring中,bean的注入有几种方式,各是什么?

7. 请简述:Spring bean的作用域?

8. 请叙述设值注入的优点?

9. 请叙述构造注入的优点?

10. 说出bean工厂创建bean的三种方式? 11. 请写出bean的生命周期的方法?

12. 请简述你对IOC的理解?

13. 请回答:IoC最大的好处是什么?

14. 简述IoC的类型?

15. Spring中依赖注入与传统编程之间的差别是什么?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Bean的生命过程
  • 二、BeanFactory 接口和 ApplicationContext 接口有什么区别 ?
  • 三、Bean的加载方式:
  • 四、请介绍一下Spring框架中Bean的生命周期和作用域
  • 五、Bean注入属性有哪几种方式?
  • 六、Spring的核心类有哪些,各有什么作用?
  • 七、Spring里面如何配置数据库驱动?
  • 八、Spring里面applicationContext.xml文件能不能改成其他文件名?
  • 九、Spring如何处理线程并发问题?
  • 十、为什么要有事物传播行为?
  • 十一、介绍一下Spring的事物管理
  • 十二、AOP
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档