spring面試題目自我解答

  1. Aop 面向切面
    是spring的一種編程思想。目的是把業務邏輯和系統邏輯區分開。我們專注的是業務邏輯,而系統邏輯不是我們關注的點,這就可以藉助於Aop幫助我們完成。還是以保存數據庫爲例:我們關注的是增刪改查,以查爲例,我們關注的代碼是用哪個字段去查,然而,操作數據庫我們必須要先開啓數據庫,加載數據庫驅動,完了還要關閉數據庫,搞不好還要回滾。很繁瑣,一急還容易給忘了,這些就屬於系統邏輯。所以Aop就出現了,幫助我們開啓關閉。我們關注與業務邏輯"查"就行了。
    Aop需要的工具包是aspectj。常見的術語有分兩類,一是:切點(apointcut),切面(aspect)。切點是哪個類或哪個方法需要加前後操作;切面是前後操作的內容。二是:前置通知(before),後置通知(after),環繞通知(around),異常通知(after-throwing)。前置通知是在切點執行前自動執行。後置通知就是在切點內容執行自動後執行。環繞通知就厲害了可以控制切點方法的執行。異常通知就是可以獲取切點拋出的異常。
    最後,對於AOP的使用,目前我見過和使用過得分兩類,一個是加在配置文件中,一個通過註解是直接加在切點方法上。前者比較隱祕,但沒有動源代碼,沒看該配置文件的人都不知道用了aop。後者比較明瞭,看到源碼就知道這裏加了aop,但動了源碼。
  2. IOC
    就是控制反轉,也可以說成依賴注入,兩種說法是一個東西。它也是一種編程思想。即有A,B兩個類,其中B類是A的一個屬性,所以也可以說成A類依賴B類。傳統的建類的方式是同時new連個類,然後把B賦值到A中。這種耦合性比較高,如果有類似B的類也要加入到A中,就要修改A類了。而控制反轉是藉助於接口創建依賴的類,即精簡了代碼,也提高了擴展性。就像下面的例子。
class A{
	private B b;

	public B getB() {
		return this.b;
	}

	public void setB(B b) {
		this.b = b;
	}
}
interface B{
	
}
class B1 implements B{
	
}
class B2 implements B{
	
}
	@Test
	public void TestDI(){
		A a=new A();
		System.out.println(a.getB());//null
		a.setB(new B1());
		System.out.println(a.getB());//test.B1@5b37e0d2
		a.setB(new B2());
		System.out.println(a.getB());//test.B2@4459eb14
	}

再者,要介紹的是依賴注入的兩種方式,上面按個是屬於setter方式注入,還有一種是構造器注入,即把依賴的類放入到構造函數參數中,當創建A類時會強制提醒創建依賴的對象。案例如下:

class A1{
	public  B b;

	public A1(B b) {
		this.b = b;
	}
	
}
interface B{
	
}
class B1 implements B{
	
}
class B2 implements B{
	
}
	@Test
	public void TestDI2(){
		A1 a1=new A1(new B1());
		System.out.println(a1.b);//test.B1@5b37e0d2
	}

最後,要介紹的就是SpringIOC容器了。這是一個負責管理創建,管理,裝配,配置對象的容器。創建A類只需要getBean這個類即可,至於A類的依賴類由spring容器負責自動創建,很方便。springIOC的實現常見的也有兩種方式,一種是在xml文件中配置。如下:

<beans>
	<bean id ="B1" class ="test.B1">
	</bean>
	<bean id="A" class="test.A">
		<property name="B">
			<ref bean="B1"/>
		</property>
	</bean>
</beans>

這類方式的源碼很複雜,主要是解析上面的xml文件和通過反射的方式遞歸創建依賴類。
另外一種是通過註解方式,形如:

@Service("A")
class A{
	@Autowired
	public B1 b1;
}
@Service("B1")
class B1{
}

兩種方式使用的時候都是通過ApplicationContext.getBean(“A”)的方式創建A類的。

總結:IOC是一種讓依賴的類自動注入創建的編程思想,對象給出他們的依賴,而不是自己創建和查找。它降低了代碼耦合,增強了擴展性。可以通過構造器注入和setter注入。在springIoc容器中,讓spring容器負責創建管理對象,可以通過在xml文件配置依賴類或者通過註解注入依賴類。最後通過getBean的方式加載類。

  1. 什麼是springBeans?
    Beans就是通常配置在applicationContext.xml文件中的Beans節點了。他們構成了spring應用的主幹類。這些bean被springIOC容器加載,這些bean默認都是單利的,可以通過設置prototypebean="false"做修改。
  2. spring bean的幾種作用域
    singleton:即單利,一個springIOC只有一個實例
    prototype:一個springIOC可以有多個實例
    request:每個http請求 都會創建一個bena,該作用域僅在web的springApplicationContext情形下有效。
    session:在一個httpSession中,一個bean對應一個實例,該作用域僅在web的springApplicationContext情形下有效。
    global-session:在一個全局HTTPsession中,一個bean對應一個實例,該作用域僅在web的springApplicationContext情形下有效。
  3. spring框架中的單利不是線程安全的。
  4. bean的生命週期
    先上個關於spring加載bean的代碼
public class Hello Implements BeanNameAware,BeanFactoryAware,BeanPostProcessor,DisposableBean{
	@Override
	public void setBeanName(String arg0){
		System.out.println("haha "+arg0);//注意 這個arg0參數是來自配置文件中bean的id
		}
	public void init(){//這個是配置文件bean要執行的init方法
		System.out.println("laiba");
		}
	@Override
	public void setBeanFactory(BeanFactory arg0)throws BeansException{
		System.out.println("haiyoushui");
		}
	@Override
	public Object postProcessAfterInitialization(Object arg0,String arg1)throws BeansException{
		
		System.out.println("postafter"+arg1);
		return arg0;//這個要返回object,否則不能執行出postProcessBeforeInitialization方法內容。
		}
		@Override
		public Object postProcessBeforeInitialization(Object arg0,String arg1)throws BeansException{
		System.out.println("postbefore");
		}
		@Override
		public void destroy()throws Exception{
			System.out.println("end...");
				
			}
		}
public class SpringTest{
	public static void main(Stringp[] args){
		ApplicationContext context =new ClassPathXmlApplicationContext(".xml");
		Hello hello=(Hello)context.getBean("hello");
		}
		}
applicationContext.xml配置文件中的bean配置:
<bean id ="hello" class="test.Hello" init-methond="init" destroy-method="destroy"/>
輸出:
haha hello
haiyoushui
laiba
postbefore
postaftercfx

從結果中可以看出,先執行setBeanName()方法,這個方法是來自BeanNameAware接口的實現。然後執行setBeanFactory方法,它是來自BeanFactoryAware接口的實現。然後是init方法,這是配置在bean中的方法。最後分別是:postProcessBeforeInitialization和postProcessAfterInitialization方法,這是來自BeanPostProcessor接口的實現。
所以spring的生命週期總結如下:
1,首先spring容器從xml文件中讀取bean的定義,並實例化,
2, spring根據bean的定義填充實例的所有屬性。
3,如果bean實現了BeanNameAware接口,spring會傳遞bean的id給setBeanName.
4,如果bean實現了BeanFactoryAware接口,spring傳遞beanFactory給setBeanFactory方法
5,執行bean的init-method方法
6,接着是實現與bean相關聯的前後置通知BeanPostProcessor,調用相應的before和after方法
7,正式使用該實例
8,如果bean實現了DisposableBean,它將調用destory方法。
總結上面的過程跟網上流行的稍微不同,一是,init-method是在前後置通知間進行的,但我測試的結果是在其前就已經執行了。二是,實例在正式使用前會檢測一列的接口實現,上面並不完整。最後是我這裏測試的destroy方法沒用執行,不知道原因。姑且與網上的流行說法爲準吧。

  1. 什麼是spring的內部bean?
    就是一個bean僅被用作另一個bean的屬性使用時,就是一個內部bean,即innerBean。這種bean通常匿名使用,並且其作用域是多例的。
  2. spring如何注入一個集合?
    spring提供了list(允許相同的值),set(不允許相同的值),hash(鍵值對),props(也是鍵值對,但鍵值都只能是string)這四種集合。
  3. 什麼是bean裝配?
    把spring容器中的bean組裝到一起,並裝載其依賴的bean
  4. 什麼是bean自動裝配?
    spring容器能夠自動裝配相互合作的bean。這個比較遍歷,不用再xml文件一個個配置各個bean的依賴,很簡潔,是大部分項目的使用方式。配置形式如下:
<bean id="customer" class="test.Hello" autowire="byName"/>
  1. spring可以注入null和空字符串
  2. spring的註解裝配方式默認是不開啓的。需要在spring配置文件中配置<context:annotation-config />元素
  3. spring支持的ORM:
    hibernate iBatis JPA TopLink JDO ojb
  4. spring支持的事務管理:
    1,編程式事務管理 ;2,聲明式事務管理。前者靈活,程序員自己寫每個增刪改查。後者通過註解或xml配置替程序員寫事務管理部分,使之更關注與業務邏輯,也就是使用了aop
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章