1. 程式人生 > >Spring部分面試題

Spring部分面試題

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)在配置 元素,通過 init-method 指定Bean的初始化方法,通過 destroy-method 指定Bean銷燬方法

<bean id="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)

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("第八步:後處理Bean,after初始化。");
        //後處理Bean,在這裡加上一個動態代理,就把這個Bean給修改了。
        return bean;//返回bean,表示沒有修改,如果使用動態代理,返回代理物件,那麼就修改了。
    }
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        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定義 在配置檔案裡面用來進行定義。 (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方法注入 構造器注入,通過 元素完成注入 setter方法注入, 通過 元素完成注入【開發中常用方式】 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
6       <property name=”url”> 
7        <value>jdbc:hsqldb:db/appfuse</value> 
8    </property> 
9
10    <property name=”username”><value>abc</value></property> 
11    <property name=”password”><value>abc</value></property> 
12</bean> 

10.Spring裡面applicationContext.xml檔案能不能改成其他檔名? ContextLoaderListener是一個ServletContextListener, 它在你的web應用啟動的時候初始化。預設情況下, 它會在WEB-INF/applicationContext.xml檔案找Spring的配置。 你可以通過定義一個元素名字為”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等都是這個類的子類。 一般事務定義步驟:

1TransactionDefinition td = new TransactionDefinition();
2TransactionStatus ts = transactionManager.getTransaction(td); 
3try{ 
4    //do sth
5    transactionManager.commit(ts);
6}catch(Exception e){
7    transactionManager.rollback(ts);
8}
spring提供的事務管理可以分為兩類:程式設計式的和宣告式的。程式設計式的,比較靈活,但是程式碼量大,存在重複的程式碼比較多;宣告式的比程式設計式的更靈活。

程式設計式主要使用transactionTemplate。省略了部分的提交,回滾,一系列的事務物件定義,需注入事務管理物件.

1void add(){
2    transactionTemplate.execute( new TransactionCallback(){ 
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通知可以被應用到一組橫跨多個物件中的方法上(例如服務層的所有業務操作)。