最近有一位朋友和我說,他作了開發 3 年了,最近去面試時,Spring 被面試官問得啞口無言,他總結了下面幾道被問到的關於 Spring 的面試題,能夠參考下。前端
1.1.定義java
1.1.1.IoC面試
1.1.2.AOP編程
Aspect Oriented Programming,面向切面編程。經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP 是 OOP 的延續,是軟件開發中的一個熱點,也是 Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用 AOP 能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。其中,最經常使用的使用場景通常有日誌模塊、權限模塊、事物模塊。後端
1.2.原理緩存
1.2.1.IoC安全
還有其餘的類不一一列舉出來,都在 java.lang.reflect 包下。說到這個模塊的時候,那麼面試官可能會考察相關的知識,主要是考察你是否真的有去了解過反射的使用。舉兩個例子: bash
這裏其實就是裏面的重要考察點就是反射對私有屬性的處理。多線程
/**
* 經過反射獲取私有的成員變量.
*/
private Object getPrivateValue(Person person, String fieldName)
{
try
{
Field field = person.getClass().getDeclaredField(fieldName);
// 主要就是這裏,須要將屬性的 accessible 設置爲 true
field.setAccessible(true);
return field.get(person);
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}複製代碼
使用默認構造函數(無參)建立的話: 架構
Class.newInstance() Constroctor constroctor = clazz.getConstructor(String.class,Integer.class); Object obj = constroctor.newInstance("name", 18);複製代碼
AOP 的內部原理其實就是動態代理和反射了。主要涉及到的反射類:
JDK 動態代理
使用 CGLIB 動態代理,被代理類不須要強制實現接口。CGLIB 不能對聲明爲 final的方法進行代理,由於 CGLIB 原理是動態生成被代理類的子類。
循環依賴就是 N 個類中循環嵌套引用,這樣會致使內存溢出。循環依賴主要分兩種:
Spring 初始化單例對象大致是分爲以下三個步驟的:
protected Object getSingleton(String beanName, boolean allowEarlyReference)
{
Object singletonObject = this.singletonObjects.get(beanName);
// isSingletonCurrentlyInCreation:判斷當前單例 bean 是否正在建立中
if(singletonObject == null && isSingletonCurrentlyInCreation(beanName))
{
synchronized(this.singletonObjects)
{
singletonObject = this.earlySingletonObjects.get(beanName);
// allowEarlyReference:是否容許從 singletonFactories 中經過 getObject 拿到
對象
if(singletonObject == null && allowEarlyReference)
{
ObjectFactory <? > singletonFactory = this.singletonFactories.get(beanName);
if(singletonFactory != null)
{
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return(singletonObject != NULL_OBJECT ? singletonObject : null);
}複製代碼
protected void addSingletonFactory(String beanName, ObjectFactory <? > singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects)
{
if(!this.singletonObjects.containsKey(beanName))
{
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}複製代碼
可能的緣由:
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>複製代碼
下面是幾種比較重要的註解類型:
ThreadLocal 和線程同步機制都是爲了解決多線程中相同變量的訪問衝突問題。在同步機制中,經過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析何時對變量進行讀寫,何時須要鎖定某個對象,何時釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。而 ThreadLocal 則從另外一個角度來解決多線程的併發訪問。 ThreadLocal 會爲每個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問衝突。由於每個線程都擁有本身的變量副本,從而也就沒有必要對該變量進行同步了。 ThreadLocal 提供了線程安全的共享對象,在編寫多線程代碼時,能夠把不安全的變量封裝進 ThreadLocal。
因爲 ThreadLocal 中能夠持有任何類型的對象,低版本 JDK 所提供的 get()返回的是 Object 對象,須要強制類型轉換。但 JDK 5.0 經過泛型很好的解決了這個問題,在必定程度地簡化 ThreadLocal 的使用。歸納起來講,對於多線程資源共享的問題,同步機制採用了「以時間換空間」的方式,而 ThreadLocal採用了「以空間換時間」的方式。前者僅提供一份變量,讓不一樣的線程排隊訪問,然後者爲每個線程都提供了一份變量,所以能夠同時訪問而互不影響。
歡迎你們一塊兒交流,喜歡文章記得關注我點個贊喲,感謝支持!
歡迎你們關注個人公衆號【以Java架構贏天下】,2019年多家公司java面試筆記整理了500多頁pdf文檔,文章都會在裏面更新,整理的資料也會放在裏面。