[Java面試五]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, 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>
//下面這段配置的含義:調用Bean2Factory的getBean2方法得到bean2
<bean id="bean2" class="cn.itcast.spring.b_instance.Bean2Factory" factory-method="getBean2"></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 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注入屬性有哪幾種方式?
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里面如何配置數據庫驅動?
<bean id=”dataSource”>
<property name=”driverClassName”>
- <value>org.hsqldb.jdbcDriver</value>
- </property>
<property name=”url”>
<value>jdbc:hsqldb:db/appfuse</value>
</property>
<property name=”username”><value>abc</value></property>
<property name=”password”><value>abc</value></property>
</bean>
10.Spring里面applicationContext.xml文件能不能改成其他文件名?
ContextLoaderListener是一個ServletContextListener, 它在你的web應用啟動的時候初始化。缺省情況下, 它會在WEB-INF/applicationContext.xml文件找Spring的配置。 你可以通過定義一個<context-param>元素名字為”contextConfigLocation”來改變Spring配置文件的 位置。示例如下:
<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>
11.Spring里面如何定義hibernate mapping?
添加hibernate mapping 文件到web/WEB-INF目錄下的applicationContext.xml文件里面。示例如下:
<property name=”mappingResources”>
<list>
<value>org/appfuse/model/User.hbm.xml</value>
</list>
</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等都是這個類的子類。
一般事務定義步驟:
TransactionDefinition td =newTransactionDefinition();
TransactionStatus ts = transactionManager.getTransaction(td);
try
{- //do sth
transactionManager.commit(ts);
}
catch(Exception e){- transactionManager.rollback(ts);
- }
編程式主要使用transactionTemplate。省略了部分的提交,回滾,一系列的事務對象定義,需注入事務管理對象.
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類似的操作。
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.通知有哪些類型?
拋出異常后通知(After throwing advice): 在方法拋出異常退出時執行的通知。
后通知(After (finally) advice):當某連接點退出的時候執行的通知 (不論是正常返回還是異常退出)。
環繞通知(Around Advice):包圍一個連接點(join point)的通知,如方法調用。這是最強大的一種通知類型。 環繞通知可以在方法調用前后完成自定義的行為。它也會選擇是否繼續執行連接點或直接返回它們自己的返回值或拋出異常來結束執行。
環繞通知是最常用的一種通知類型。大部分基於攔截的AOP框架,例如Nanning和JBoss4,都只提供環繞通知。
切入點(pointcut)和連接點(join point)匹配的概念是AOP的關鍵,這使得AOP不同於其它僅僅提供攔截功能的舊技術。 切入點使得定位通知(advice)可獨立於OO層次。 例如,一個提供聲明式事務管理的around通知可以被應用到一組橫跨多個對象中的方法上(例如服務層的所有業務操作)。