天天看點

Spring總結以及在面試中的一些問題.[Java面試五]Spring總結以及在面試中的一些問題.

[Java面試五]Spring總結以及在面試中的一些問題.

轉自:http://www.cnblogs.com/wang-meng/p/5701982.html

1.談談你對spring IOC和DI的了解,它們有什麼差別?

IoC Inverse of Control 反轉控制的概念,就是将原本在程式中手動建立UserService對象的控制權,交由Spring架構管理,簡單說,就是建立UserService對象控制權被反轉到了Spring架構

DI:Dependency Injection 依賴注入,在Spring架構負責建立Bean對象時,動态的将依賴對象注入到Bean元件

面試題: IoC 和 DI的差別?

IoC 控制反轉,指将對象的建立權,反轉到Spring容器 , DI 依賴注入,指Spring建立對象的過程中,将對象依賴屬性通過配置進行注入

2.BeanFactory 接口和 ApplicationContext 接口有什麼差別 ?

    ①ApplicationContext 接口繼承BeanFactory接口,Spring核心工廠是BeanFactory ,BeanFactory采取延遲加載,第一次getBean時才會初始化Bean, ApplicationContext是會在加載配置檔案時初始化Bean。

    ②ApplicationContext是對BeanFactory擴充,它可以進行國際化處理、事件傳遞和bean自動裝配以及各種不同應用層的Context實作 

開發中基本都在使用ApplicationContext, web項目使用WebApplicationContext ,很少用到BeanFactory

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

IHelloService helloService = (IHelloService) beanFactory.getBean("helloService");

helloService.sayHello();

3.spring配置bean執行個體化有哪些方式?

    1)使用類構造器執行個體化(預設無參數)

<bean id="bean1" class="cn.itcast.spring.b_instance.Bean1"></bean>

    2)使用靜态工廠方法執行個體化(簡單工廠模式)

//下面這段配置的含義:調用Bean2Factory的getBean2方法得到bean2

<bean id="bean2" class="cn.itcast.spring.b_instance.Bean2Factory" factory-method="getBean2"></bean>

    3)使用執行個體工廠方法執行個體化(工廠方法模式)

//先建立工廠執行個體bean3Facory,再通過工廠執行個體建立目标bean執行個體

<bean id="bean3Factory" class="cn.itcast.spring.b_instance.Bean3Factory"></bean>

<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>

4.簡單的說一下spring的生命周期?

    1)在配置 <bean> 元素,通過 init-method 指定Bean的初始化方法,通過 destroy-method 指定Bean銷毀方法

<beanid="lifeCycleBean"class="cn.itcast.spring.d_lifecycle.LifeCycleBean"init-method="setup"destroy-method="teardown"></bean>

需要注意的問題:

    *  destroy-method 隻對 scope="singleton" 有效 

    *  銷毀方法,必須關閉ApplicationContext對象(手動調用),才會被調用

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

applicationContext.close();

    2)Bean的完整生命周期 (十一步驟)【了解内容,但是對于spring内部操作了解有一定幫助】

①instantiate bean對象執行個體化

②populate properties 封裝屬性

③如果Bean實作BeanNameAware 執行 setBeanName

④如果Bean實作BeanFactoryAware 或者 ApplicationContextAware 設定工廠 setBeanFactory 或者上下文對象 setApplicationContext

⑤如果存在類實作 BeanPostProcessor(後處理Bean) ,執行postProcessBeforeInitialization,BeanPostProcessor接口提供鈎子函數,用來動态擴充修改Bean。(程式自動調用後處理Bean)

publicclassMyBeanPostProcessorimplementsBeanPostProcessor{

publicObject postProcessAfterInitialization(Object bean,String beanName)

throwsBeansException{

System.out.println("第八步:後處理Bean,after初始化。");

//後處理Bean,在這裡加上一個動态代理,就把這個Bean給修改了。

return bean;//傳回bean,表示沒有修改,如果使用動态代理,傳回代理對象,那麼就修改了。

}

publicObject postProcessBeforeInitialization(Object bean,String beanName)

throwsBeansException{

System.out.println("第五步:後處理Bean的:before初始化!!");

//後處理Bean,在這裡加上一個動态代理,就把這個Bean給修改了。

return bean;//傳回bean本身,表示沒有修改。

}

}

注意:這個前處理Bean和後處理Bean會對所有的Bean進行攔截。

⑥如果Bean實作InitializingBean 執行 afterPropertiesSet

⑦調用<bean init-method="init"> 指定初始化方法 init

⑧如果存在類實作 BeanPostProcessor(處理Bean) ,執行postProcessAfterInitialization

⑨執行業務處理

⑩如果Bean實作 DisposableBean 執行 destroy

⑪調用<bean destroy-method="customerDestroy"> 指定銷毀方法 customerDestroy

5.請介紹一下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情形下有效。

6.Bean注入屬性有哪幾種方式?

spring支援構造器注入和setter方法注入

    構造器注入,通過 <constructor-arg> 元素完成注入

    setter方法注入, 通過<property> 元素完成注入【開發中常用方式】

7.什麼是AOP,AOP的作用是什麼?

面向切面程式設計(AOP)提供另外一種角度來思考程式結構,通過這種方式彌補了面向對象程式設計(OOP)的不足,除了類(classes)以外,AOP提供了切面。切面對關注點進行子產品化,例如橫切多個類型和對象的事務管理

Spring的一個關鍵的元件就是AOP架構,可以自由選擇是否使用AOP 提供聲明式企業服務,特别是為了替代EJB聲明式服務。最重要的服務是聲明性事務管理,這個服務建立在Spring的抽象事物管理之上。允許使用者實作自定義切面,用AOP來完善OOP的使用,可以把Spring AOP看作是對Spring的一種增強

8.Spring的核心類有哪些,各有什麼作用?

BeanFactory:産生一個新的執行個體,可以實作單例模式

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

ApplicationContext:提供架構的實作,包括BeanFactory的所有功能

9.Spring裡面如何配置資料庫驅動?

使用”org.springframework.jdbc.datasource.DriverManagerDataSource”資料源來配置資料庫驅動。示例如下:

  1. <bean id=”dataSource”> 

  2.     <property name=”driverClassName”> 

  3.         <value>org.hsqldb.jdbcDriver</value>
  4.     </property> 
  5.     <property name=”url”> 

  6.         <value>jdbc:hsqldb:db/appfuse</value> 

  7.     </property> 

  8.     <property name=”username”><value>abc</value></property> 

  9.     <property name=”password”><value>abc</value></property> 

  10. </bean> 

10.Spring裡面applicationContext.xml檔案能不能改成其他檔案名?

ContextLoaderListener是一個ServletContextListener, 它在你的web應用啟動的時候初始化。預設情況下, 它會在WEB-INF/applicationContext.xml檔案找Spring的配置。 你可以通過定義一個<context-param>元素名字為”contextConfigLocation”來改變Spring配置檔案的 位置。示例如下: 

  1. <listener> 

  2.     <listener-class>org.springframework.web.context.ContextLoaderListener

  3.         <context-param> 

  4.          <param-name>contextConfigLocation</param-name> 

  5.          <param-value>/WEB-INF/xyz.xml</param-value> 

  6.         </context-param>   

  7.     </listener-class> 

  8. </listener> 

11.Spring裡面如何定義hibernate mapping?

添加hibernate mapping 檔案到web/WEB-INF目錄下的applicationContext.xml檔案裡面。示例如下:

  1. <property name=”mappingResources”> 

  2.     <list> 

  3.         <value>org/appfuse/model/User.hbm.xml</value> 

  4.     </list> 

  5. </property>

12.Spring如何處理線程并發問題?

Spring使用ThreadLocal解決線程安全問題

我們知道在一般情況下,隻有無狀态的Bean才可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非線程安全狀态采用ThreadLocal進行處理,讓它們也成為線程安全的狀态,因為有狀态的Bean就可以在多線程中共享了。

ThreadLocal和線程同步機制都是為了解決多線程中相同變量的通路沖突問題。

在同步機制中,通過對象的鎖機制保證同一時間隻有一個線程通路變量。這時該變量是多個線程共享的,使用同步機制要求程式慎密地分析什麼時候對變量進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放對象鎖等繁雜的問題,程式設計和編寫難度相對較大。

而ThreadLocal則從另一個角度來解決多線程的并發通路。ThreadLocal會為每一個線程提供一個獨立的變量副本,進而隔離了多個線程對資料的通路沖突。因為每一個線程都擁有自己的變量副本,進而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

由于ThreadLocal中可以持有任何類型的對象,低版本JDK所提供的get()傳回的是Object對象,需要強制類型轉換。但JDK5.0通過泛型很好的解決了這個問題,在一定程度地簡化ThreadLocal的使用。

概括起來說,對于多線程資源共享的問題,同步機制采用了“以時間換空間”的方式,而ThreadLocal采用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊通路,而後者為每一個線程都提供了一份變量,是以可以同時通路而互不影響。

13.為什麼要有事物傳播行為?

14.介紹一下Spring的事物管理

    事務就是對一系列的資料庫操作(比如插入多條資料)進行統一的送出或復原操作,如果插入成功,那麼一起成功,如果中間有一條出現異常,那麼復原之前的所有操作。這樣可以防止出現髒資料,防止資料庫資料出現問題。

開發中為了避免這種情況一般都會進行事務管理。Spring中也有自己的事務管理機制,一般是使用TransactionMananger進行管 理,可以通過Spring的注入來完成此功能。spring提供了幾個關于事務處理的類:

TransactionDefinition //事務屬性定義

TranscationStatus //代表了目前的事務,可以送出,復原。

PlatformTransactionManager這個是spring提供的用于管理事務的基礎接口,其下有一個實作的抽象類 AbstractPlatformTransactionManager,我們使用的事務管理類例如 DataSourceTransactionManager等都是這個類的子類。

一般事務定義步驟:

  1. TransactionDefinition td =newTransactionDefinition();

  2. TransactionStatus ts = transactionManager.getTransaction(td);

  3. try

  4.     //do sth
  5.     transactionManager.commit(ts);

  6. }

    catch(Exception e){
  7.     transactionManager.rollback(ts);
  8. }

    spring提供的事務管理可以分為兩類:程式設計式的和聲明式的。程式設計式的,比較靈活,但是代碼量大,存在重複的代碼比較多;聲明式的比程式設計式的更靈活。

程式設計式主要使用transactionTemplate。省略了部分的送出,復原,一系列的事務對象定義,需注入事務管理對象.

  1. void add(){

  2.     transactionTemplate.execute(newTransactionCallback(){

  3.         pulic Object doInTransaction(TransactionStatus ts){
  4.          //do sth
  5.         }
  6.     }

  7. }

聲明式:

使用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類似的操作。

15.解釋一下Spring AOP裡面的幾個名詞

切面(Aspect):一個關注點的子產品化,這個關注點可能會橫切多個對象。事務管理是J2EE應用中一個關于橫切關注點的很好的例子。 在Spring AOP中,切面可以使用通用類(基于模式的風格) 或者在普通類中以 @Aspect 注解(@AspectJ風格)來實作。

連接配接點(Joinpoint):在程式執行過程中某個特定的點,比如某方法調用的時候或者處理異常的時候。 在Spring AOP中,一個連接配接點 總是 代表一個方法的執行。 通過聲明一個org.aspectj.lang.JoinPoint類型的參數可以使通知(Advice)的主體部分獲得連接配接點資訊。

通知(Advice):在切面的某個特定的連接配接點(Joinpoint)上執行的動作。通知有各種類型,其中包括“around”、“before”和“after”等通知。 通知的類型将在後面部分進行讨論。許多AOP架構,包括Spring,都是以攔截器做通知模型, 并維護一個以連接配接點為中心的攔截器鍊。

切入點(Pointcut):比對連接配接點(Joinpoint)的斷言。通知和一個切入點表達式關聯,并在滿足這個切入點的連接配接點上運作(例如,當執行某個特定名稱的方法時)。 切入點表達式如何和連接配接點比對是AOP的核心:Spring預設使用AspectJ切入點文法。

引入(Introduction):(也被稱為内部類型聲明(inter-type declaration))。聲明額外的方法或者某個類型的字段。 Spring允許引入新的接口(以及一個對應的實作)到任何被代理的對象。例如,你可以使用一個引入來使bean實作 IsModified 接口,以便簡化緩存機制。

目标對象(Target Object): 被一個或者多個切面(aspect)所通知(advise)的對象。也有人把它叫做 被通知(advised) 對象。 既然Spring AOP是通過運作時代理實作的,這個對象永遠是一個 被代理(proxied) 對象。

AOP代理(AOP Proxy): AOP架構建立的對象,用來實作切面契約(aspect contract)(包括通知方法執行等功能)。 在Spring中,AOP代理可以是JDK動态代理或者CGLIB代理。 注意:Spring 2.0最新引入的基于模式(schema-based)風格和@AspectJ注解風格的切面聲明,對于使用這些風格的使用者來說,代理的建立是透明的。

織入(Weaving):把切面(aspect)連接配接到其它的應用程式類型或者對象上,并建立一個被通知(advised)的對象。 這些可以在編譯時(例如使用AspectJ編譯器),類加載時和運作時完成。 Spring和其他純Java AOP架構一樣,在運作時完成織入。

16.通知有哪些類型?

前置通知(Before advice):在某連接配接點(join point)之前執行的通知,但這個通知不能阻止連接配接點前的執行(除非它抛出一個異常)。

傳回後通知(After returning advice):在某連接配接點(join point)正常完成後執行的通知:例如,一個方法沒有抛出任何異常,正常傳回。 

抛出異常後通知(After throwing advice):在方法抛出異常退出時執行的通知。 

後通知(After (finally) advice):當某連接配接點退出的時候執行的通知(不論是正常傳回還是異常退出)。 

環繞通知(Around Advice):包圍一個連接配接點(join point)的通知,如方法調用。這是最強大的一種通知類型。 環繞通知可以在方法調用前後完成自定義的行為。它也會選擇是否繼續執行連接配接點或直接傳回它們自己的傳回值或抛出異常來結束執行。 

環繞通知是最常用的一種通知類型。大部分基于攔截的AOP架構,例如Nanning和JBoss4,都隻提供環繞通知。 

切入點(pointcut)和連接配接點(join point)比對的概念是AOP的關鍵,這使得AOP不同于其它僅僅提供攔截功能的舊技術。 切入點使得定位通知(advice)可獨立于OO層次。 例如,一個提供聲明式事務管理的around通知可以被應用到一組橫跨多個對象中的方法上(例如服務層的所有業務操作)。