Spring簡介
Spring解決的最核心的問題就是把對象之間的依賴關系轉為用配置文件來管理,這個是通過Spring的依賴注入機制實現的。
Spring Bean裝配
1. IOC的概念以及在Spring容器中如何進行IOC的操作。
IOC:Inversion of Control,控制反轉。在Java開發中,IOC意味着將你設計好的類交給系統去控制,而不是在你的類內部控制,這稱為控制反轉,就是被調用類的實例由原先的調用類控制創建、銷毀現在轉變成由Spring的容器管理。
2. Spring容器是如何管理Bean的生命周期的(如Bean的初始化方法,Bean的銷毀方法)
創建:<bean name=”” class=”” 額外屬性>
初始化:配置init-method/實現接口InitializingBean
調用:context.getBean(),進行方法的調用
銷毀:配置destroy-method/實現DisposableBean接口
3. DI的概念以及在Spring框架注入有幾種方式。使用構造注入對象,必須要注意什么問題?
注入方式:
構造注入[構造方法注入]
屬性注入[屬性的SET/GET]
方法注入[工廠注入]
<!-- 構造函數注入 --> <bean id="user1" class="com.spring.test.model.User"> <constructor-arg index="0" type="String" value="Lu"></constructor-arg> <constructor-arg index="1" type="String" value="123456"></constructor-arg> </bean> <!-- 屬性注入 --> <bean id="user2" class="com.spring.test.model.User"> <property name="username" value="Luxx"></property> <property name="password" value="56789"></property> </bean> <!-- 工廠注入 --> <bean id="userFactory" class="com.spring.test.factory.UserFactory"/> <bean id="user3" factory-bean="userFactory" factory-method="createUser"></bean> <!-- 靜態工廠注入 --> <bean id="user4" class="com.spring.test.factory.UserFactoryStatic" factory-method="createUser"></bean>
使用構造函數依賴注入時,Spring保證所有一個對象所有依賴的對象先實例化后,才實例化這個對象。使用set方法依賴注入時,Spring首先實例化對象,然后才實例化所有依賴的對象。
4. 使用DI注入時,Property代表什么意思,如果property引用的是其他Bean的話,如何注入,如果引用是字符串的話,如何設置。
使用DI注入時,Property代表注入類的屬性,如果應用其他的bean用ref屬性來表明被引用bean的名稱,如果是引用字符串的話,用value屬性。如:
<property name=”userDao” ref=”被引用bean的名稱” /> <property name=”username” value = “字符串”/>
5. Bean的作用域
所有Spring Bean的默認都是單例,即scope=”singleton”
幾種作用域:
singleton:在每一個Spring容器中,一個Bean定義只有一個對象實例。
prototype:Bean的定義可以被實例化任意次(每次調用都創建一個實例)。
request:在一次Http 請求中,每個Bean定義對應一個實例。該作用域僅在基於Web的Spring上下文(如Spring MVC)中才有效。
Session:在一個Http Session中,每個Bean定義對應一個實例。該作用域僅在基於Web的Spring上下文(如Spring MVC)中才有效。
Global-session:在一個全局Http Session中,每個Bean定義對應一個實例。該作用域僅在Portlet上下文中才有效。
6. DI自動裝配(autowiring)
Spring中提供了自動裝配依賴對象的機制,但是在實際應用中並不推薦使用自動裝配,因為自動裝配會產生未知情況,開發人員無法預見最終的裝配結果。
自動裝配是在配置文件中實現的,如下:
<bean id="***" class="***" autowire="byName">
只需要配置一個@Autowired屬性即可完成自動裝配,不用再配置文件中寫<property>,但是在類中還是要生成依賴對象的setter方法。
Autowire的屬性值有如下幾個:
1)byName 按名稱裝配,可以根據屬性的名稱(或者ID)在容器中查詢與該屬性名稱(或者ID)相同的bean,如果沒有找到,則屬性值為null;
2)byType 按類型裝配,可以根據屬性類型,在容器中尋找該類型匹配的bean,如有多個,則會拋出異常,如果沒有找到,則屬性值為null;如果有多個,使用bean的primary屬性,注意:這個默認就是true,需要把非候選的bean的primary的屬性設置為false。排除某些bean,設置某些bean的autowire-candidate屬性為false。
3)constructor 與byType方式相似,不同之處在與它應用於構造器參數,如果在容器中沒有找到與構造器參數類型一致的bean,那么將拋出異常;
4)autodetect 通過bean類的自省機制(introspection)來決定是使用constructor還是byType的方式進行自動裝配。首先嘗試使用constructor 進行自動裝配。如果失敗,再嘗試使用byType的方式。
可選的自動裝配:默認情況下,@Autowired具有強契約特性,其所標注的屬性或參數必須是可裝配的,如果沒有,則自動裝配失敗(拋出NoSuchBeanDefinitionException)。屬性不一定要裝配,null值也是可以接受的,使用@Autowired(required=false)來配置是可選的。
限定歧義性的依賴:使用@Qualifier(“bean id”),通過制定Bean的ID把選擇范圍縮小到只剩下一個Bean。
注意:顯式的指定依賴,比如property和constructor-arg元素,總會覆蓋自動裝配。自動裝配的行為可以和依賴檢查結合使用,依賴檢查會在自動裝配完成后發生。
7. DI自動檢測(autodiscovery)
配置Spring自動檢測Bean的定義和自動裝配Bean:
<context:component-scan base-package="com.spring.test"/>
默認情況下,<context:component-scan>查找使用構造型注解所標注的類,這些注解如下:
@Component 通用的構造型注解,標識該類為Spring組件。
@Controller 標識該類為Spring MVC controller。
@Repository 標識該類為數據倉庫,一般作為DAO層的注解。
@Service 標識該類為服務,一般作為服務層的注解。
使用@Component標注的任意自定義注解。
Spring AOP
AOP的概念以及使用AOP機制有什么好處。
AOP的概念是Aspect Oriented Programming面向切面編程。本質上就是代理模式。
好處:AOP將程序分解成各個方面或者說關注點,這使得可以模塊化,相當橫向上分切了。它可以解決OOP和過程化方法不能夠很好解決的橫切(cross-cutting)問題,如:事務、安全、日志等橫切關注。
Spring+AspectJ 實現AOP的2種方式:
1) 使用注解(@AspectJ)實現AOP:
@Aspect @Component public class LogAspect { @Before("execution(public * com.spring.test.service.*.*(..))") public void beforeService(){ System.out.println("Before ..."); } @After("execution(public * com.spring.test.service.*.*(..))") public void afterService(){ System.out.println("After ..."); } @AfterReturning("execution(public * com.spring.test.service.UserService.save(com.spring.test.model.User)) and args(user)") public void logAfterReturn(User user){ System.out.println("After return..."+user); } }
開啟注解掃描:
xmlns:aop=http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd <context:component-scan base-package="com.spring.test"/> <aop:aspectj-autoproxy proxy-target-class="true"/>
注意的是 proxy-target-class="true" 屬性,它的默認值是 false,默認只能代理接口(使用 JDK 動態代理),當為 true 時,才能代理目標類(使用 CGLib 動態代理)。
2)另一種XML配置方式:
public class LogAspect { public void beforeService(){ System.out.println("Before ..."); } public void afterService(){ System.out.println("After ..."); } public void logAfterReturn(User user){ System.out.println("After return..."+user); } }
配置:
<bean id="logAspect" class="com.spring.test.aop.LogAspect" /> <aop:config> <aop:aspectref="logAspect"> <aop:pointcut id="serviceAction" expression="execution(public * com.spring.test.service.*.*(..))"/> <aop:beforepointcut-ref="serviceAction" method="beforeService"/> <aop:afterpointcut-ref="serviceAction" method="afterService"/> <aop:pointcutid="serviceReturnAction" expression="execution(public * com.spring.test.service.UserService.save(com.spring.test.model.User)) and args(user)"/> <aop:after-returningpointcut-ref="serviceReturnAction" method="logAfterReturn" arg-names="user"/> </aop:aspect> </aop:config>
使用 <aop:config> 元素來進行 AOP 配置,在其子元素中配置切面,包括增強類型、目標方法、切點等信息。
參考:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/index.html
http://oss.org.cn/ossdocs/framework/spring/zh-cn/beans.html
