-
什么是接口?
查看全部 -
為什么使用框架
查看全部 -
什么是框架?
查看全部 -
Spring適用范圍
查看全部 -
Spring作用
查看全部 -
Spring Framework Runtime
查看全部 -
Spring是什么
查看全部 -
AspectJ介紹及Pointcut注解應(yīng)用
1、@AspectJ的風(fēng)格類似純java注解的普通java類。
2、Spring可以使用AspectJ來做切入點(diǎn)解析。
3、AOP的運(yùn)行時仍舊是純的SpringAOP,對AspectJ的編譯器或者織入無依賴性。
Spring中配置@AspectJ
1、對@AspectJ支持可以使用XML或者Java注解類型的配置(@EnableAspectJAutoProxy使用AspectJ進(jìn)行自動代理)
2、前提:確保AspectJ的aspectjweaver.jar庫包含在應(yīng)用程序(版本1.6.8或更高版本)的classpath中,以Spring4.0.5為基準(zhǔn)的,其他版本可能不一樣(可以根據(jù)具體情況查找Spring具體文檔)。
aspect注解的具體使用
1、@AspectJ切面使用@Aspect注解配置,擁有@Aspect的任何bean將被Spring自動識別并應(yīng)用。
2、@Aspect注解的類可以有方法和字段,他們也可能包括切入點(diǎn)(pointcut),通知(Advice)和引入(introduction)聲明。
3、@Aspect注解是不能夠通過類路徑自動檢測發(fā)現(xiàn)的,所以需要配合使用@Component注釋或者在xml配置bean(@Aspect注解的類配置在xml中)。
4、一個類中的@Aspect注解標(biāo)識它為一個切面,并且將自己從自動代理中排出。
如何定義一個切入點(diǎn)
1、一個切入點(diǎn)通過一個普通的方法定義來提供,并且切入點(diǎn)表達(dá)式使用@Pointcut注解,方法返回類型必須為void
2、定義一個名為'anyOldTransfer',這個切入點(diǎn)將匹配任何名為“transfer”的方法的執(zhí)行。
切入點(diǎn)支持哪些定義方式
組合Pointcut
1、切入點(diǎn)表達(dá)式可以通過&&、||和!進(jìn)行組合,也可以通過名字引用切入點(diǎn)表達(dá)式。
2、通過組合,可以建立更加復(fù)雜的切入點(diǎn)表達(dá)式。
如何定義良好的pointcuts
1、AspectJ是編譯期的AOP
2、檢查代碼并匹配連接點(diǎn)與切入點(diǎn)的代價是昂貴的。
3、一個好的切入點(diǎn)應(yīng)該包括以下幾點(diǎn)
【a】選擇特定類型的連接點(diǎn),如:execution,get,set,call,handler。
【b】確定連接點(diǎn)范圍,如:within,withincode。
【c】匹配上下文信息,如:this,target,@annotation。
查看全部 -
ProxyFactoryBean及相關(guān)內(nèi)容(下)
Proxying classes
1、前面的例子中如果沒有Person(BizLogic)接口,這種情況下Spring會使用CGLIB代理,而不是JDK動態(tài)代理。
2、可以強(qiáng)制使用CGLIB,即使有接口的情況下。
3、CGLIB代理的工作原理是在運(yùn)行時生成目標(biāo)類的子類,Spring配置這個生成的子類委托方法調(diào)用到原來的目標(biāo)
4、子類是用來實(shí)現(xiàn)Decorator模式,織入通知
5、CGLIB的代理對用戶是透明的,需要注意:
【1】final方法不能被通知,因?yàn)樗鼈儾荒鼙桓采w。
【2】不用把CGLIB添加到classpath中,在Spring3.2中,CGLIB被重新包裝并包含在Spring核心JAR(即基于CGLIB的AOP就像JDK動態(tài)代理一樣“開箱即用”,也就是說不用手動引入CGLIB這個包)
?使用global advisors:使*做通配符,匹配所有攔截器加入通知鏈
實(shí)現(xiàn)了MethodInterceptor這個類似的方式,才可以使用通配符的方式。
簡化的proxy定義
1、Spring中支持父子bean定義的方式,以及內(nèi)部bean定義,可以帶來更簡潔的代理定義(抽象屬性標(biāo)記父bean定義為抽象的這樣它不能被實(shí)例化)
Spring官方文檔給出的例子(TransactionProxyFactoryBean是基于事物的代理Bean)通過getBean獲得的是TransactionProxyFactoryBean的實(shí)例
使用ProxyFactory的好處:
1、使用SpringAOP而不必依賴于SpringIOC
2、大多數(shù)情況下最佳實(shí)踐是用IoC容器創(chuàng)建AOP代理。
3、雖然可以硬編碼方式實(shí)現(xiàn),但是Spring推薦使用配置或注解方式實(shí)現(xiàn)。
使用auto-proxy
1、Spring也允許使用“自動代理”的bean定義,它可以自動代理選定的bean,這是建立在Spring的“bean post processor”功能基礎(chǔ)上的(在加載bean的時候就可以修改)
2、主要通過BeanNameAutoProxyCreator實(shí)現(xiàn)(自動代理所有以jdk開始的Bean,也包括onlyJdk這種Bean)
3、DefaultAdvisorAutoProxyCreator,當(dāng)前IoC容器中自動應(yīng)用,來達(dá)到創(chuàng)建動態(tài)代理的效果,不用顯示聲明引用advisor的bean定義
查看全部 -
ProxyFactoryBean及相關(guān)內(nèi)容(下)
Proxying classes
1、前面的例子中如果沒有Person(BizLogic)接口,這種情況下Spring會使用CGLIB代理,而不是JDK動態(tài)代理。
2、可以強(qiáng)制使用CGLIB,即使有接口的情況下。
3、CGLIB代理的工作原理是在運(yùn)行時生成目標(biāo)類的子類,Spring配置這個生成的子類委托方法調(diào)用到原來的目標(biāo)
4、子類是用來實(shí)現(xiàn)Decorator模式,織入通知
5、CGLIB的代理對用戶是透明的,需要注意:
【1】final方法不能被通知,因?yàn)樗鼈儾荒鼙桓采w。
【2】不用把CGLIB添加到classpath中,在Spring3.2中,CGLIB被重新包裝并包含在Spring核心JAR(即基于CGLIB的AOP就像JDK動態(tài)代理一樣“開箱即用”,也就是說不用手動引入CGLIB這個包)
?使用global advisors:使*做通配符,匹配所有攔截器加入通知鏈
查看全部 -
ProxyFactoryBean及相關(guān)內(nèi)容(上)
1、通過Spring API創(chuàng)建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
2、ProxyFactoryBean可以完全控制切入點(diǎn)和通知(advice)以及他們的順序。(和其它工廠Bean實(shí)現(xiàn)方式是一樣的,都引入了一個中間層)
假如有這樣一種情況:定義了一個Bean的Id為foo的ProxyFactoryBean,那么引用foo這個對象,看到的將不是ProxyFactoryBean本身,而是ProxyFactoryBean這個類通過getObject()方法創(chuàng)建的對象。
getObject():將創(chuàng)建一個AOP代理包裝一個目標(biāo)對象。(ProxyFactoryBean通過這種方式達(dá)到代理的目的)
3、使用ProxyFactoryBean或者其它IoC相關(guān)類來創(chuàng)建AOP代理的最重要好處是因?yàn)橥ㄖ颓腥朦c(diǎn)也可以由IoC來管理。
4、當(dāng)被代理類沒有實(shí)現(xiàn)任何接口,使用CGLIB代理,否則使用JDK代理。
5、通過設(shè)置proxyTargetClass為true,可強(qiáng)制使用CGLIB代理(無論代理類是否實(shí)現(xiàn)接口)
6、如果目標(biāo)類實(shí)現(xiàn)了一個(或者多個)接口,那么創(chuàng)建代理的類型將依賴ProxyFactoryBean的配置。(因?yàn)镻roxyFactoryBean里有一個ProxyInterfaces屬性,該屬性可以查看該類實(shí)現(xiàn)了哪些接口)
7、如果ProxyFactoryBean的proxyInterfaces屬性被設(shè)置為一個或者多個全限定接口名(包括包名、類名、完整的名稱),基于JDK的代理將被創(chuàng)建。
8、如果ProxyFactoryBean的proxyInterfaces屬性沒有被設(shè)置,但是目標(biāo)類實(shí)現(xiàn)了一個(或者更多)接口,那么ProxyFactoryBean將自動檢測到這個目標(biāo)類已經(jīng)實(shí)現(xiàn)了至少一個接口,創(chuàng)建一個基于JDK的代理。
例子:創(chuàng)建基于接口的代理
ProxyFactoryBean工作原理:首先,定義了一個Id為personTarget的Bean,又定義了一個Id為myAdvisor的Bean,定義了一個Id為debugInterceptor的Bean,重點(diǎn)在接下來的定義,定義了一個Id為person的Bean,但是對應(yīng)的并不是Person類,而是Spring提供的ProxyFactoryBean這個類,并且這個Bean配置里有一個屬性名為proxyInterfaces的<property>配置,并且它的value值為Person的路徑,另外一個<property>標(biāo)簽屬性名稱為targer并且指向personTarget(這個類是Person的具體實(shí)現(xiàn)類),當(dāng)我們get()Id為person這個Bean時,返回的并不是ProxyFactoryBean的對象,而是ProxyFactoryBean里的getObject()返回的對象,它返回的是屬性名為target指向的personTarget的對象,通過ProxyFactoryBean創(chuàng)建代理的時候,可以指定它的interceptor,interceptorNames屬性,是一個集合,可以通過List、Value指定它的具體內(nèi)容。
案例:(通過Spring API實(shí)現(xiàn)通知)
各種通知的類前面已經(jīng)寫好了,所以主要進(jìn)行XML配置。
public interface BizLogic {
String save();
}
public class BizLogicImpl implements BizLogic {
@Override
public String save() {
System.out.println("BizLogicImpl: BizLogicImpl save");
return "BizLogicImpl save";
}
}
XML配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? xsi:schemaLocation="http://www.springframework.org/schema/beans
? ? ? ? http://www.springframework.org/schema/beans/spring-beans.xsd"?
? ? ? ? default-autowire="constructor">
? ?<bean id="afterReturningAdvice" class="springAPI.MoocAfterReturningAdvice" ></bean>
? ? ? <bean id="beforeAdvice" class="springAPI.MoocBeforeAdvice" ></bean>
? ? ? <bean id="methodInterceptor" class="springAPI.MoocMethodInterceptor" ></bean>
? ? ? <bean id="throwsAdvice" class="springAPI.MoocThrowsAdvice" ></bean>
? ?<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
? ?<property name="mappedNames">
? ?<list>
? ?<value>sa*</value>
? ?</list>
? ?</property>
? ?</bean>
? ?<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
? ?<property name="advice" ref="beforeAdvice"></property>
? ?<property name="pointcut" ref="pointcutBean"></property>
? ?</bean>
? ?<bean id="bizLogicImplTarget" class="springAPI.BizLogicImpl"></bean>
? ?<bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
? ?<property name="target"><ref bean="bizLogicImplTarget"/></property>
? ?<property name="interceptorNames">
? ?<list>
? ?<value>afterReturningAdvice</value>
? ? ? <value>beforeAdvice</value>
? ? ? <value>methodInterceptor</value>
<!-- ? ? ? <value>throwsAdvice</value>
?--> ??
? ?</list>
? ?</property>
? ?</bean>?
? ?
?</beans>
測試:
@Test
public void testApi(){
ApplicationContext ac=new ClassPathXmlApplicationContext("spring-ioc.xml");
BizLogic bl=(BizLogic)ac.getBean("bizLogicImpl");
bl.save();
}
結(jié)果:
前置通知的方法:save ? springAPI.BizLogicImpl
環(huán)繞前通知實(shí)現(xiàn)了
BizLogicImpl: BizLogicImpl save
環(huán)繞后通知實(shí)現(xiàn)了
返回后通知方法執(zhí)行了save ?springAPI.BizLogicImpl ?null
查看全部 -
Spring的API實(shí)現(xiàn)AOP功能
1、這是Spring1.2的歷史用法,現(xiàn)在Spring4.0仍然支持。
2、這是SpringAOP的基礎(chǔ)
使用Spring的API實(shí)現(xiàn)AOP的原因:Schema-based(配置文件)和AspectJ實(shí)現(xiàn)AOP完全可以滿足我們使用AOP的功能,使用API是因?yàn)檫@是SpringAOP的基礎(chǔ),可以加深我們應(yīng)用和了解SpringAOP的理解(無論是注解方式、還是XML配置文件的方式,最終實(shí)現(xiàn)的基礎(chǔ)都是和API密切關(guān)系的)。
3、現(xiàn)在SpringAOP的用法也是基于歷史的,只是更簡便了(在Spring1.2時配置文件很多,還需要了解各種配置)。
Spring的API
一、Pointcut(作為一個接口,有幾個實(shí)現(xiàn)類)
1、Pointcut接口的實(shí)現(xiàn)類之一:NameMatchMethodPointcut,根據(jù)方法名字進(jìn)行匹配。
2、該類有一個成員變量:mappedNames(它是一個集合,存放用于匹配的方法的名稱),匹配方法的集合。
配置文件的例子:(sa開頭的所有方法進(jìn)行切入)
二、Before advice(原理:單獨(dú)寫一個前置通知的類,并實(shí)現(xiàn)MethodBeforeAdvice接口,并實(shí)現(xiàn)該接口的方法,)
1、一個簡單的通知類型。
2、執(zhí)行邏輯方法前被調(diào)用,不需要MethodInvocation對象。
3、前置通知可以在連接點(diǎn)執(zhí)行之前插入自定義行為,但不能改變返回值。
案例:(會使用到后面的知識,暫時編寫這些)
public class MoocBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] object, Object target) throws Throwable {
System.out.println("前置通知的方法:" + method.getName() + " ? " + target.getClass().getName());
}
}
三、Throws advice
1、如果連接點(diǎn)(執(zhí)行的業(yè)務(wù)方法)出現(xiàn)異常,throws advice在方法返回后被調(diào)用。
2、如果throws-advice的方法拋出異常,那么它將覆蓋原有異常。
3、接口org.springframework.aop.ThrowAdvice不包含任何方法,僅僅是一個聲明,其實(shí)現(xiàn)類一定要實(shí)現(xiàn)類似這樣的方法,void afterThrowing([Method, args, target],ThrowableSubclass);
Throws advice發(fā)生異常的說明
public void afterThrowing(Exception ex);//只有一個異常。
public void afterThrowing(RemoteException ex);//另外一種類型的異常。
?public void afterThrowing(Method method,Object[] args(目標(biāo)參數(shù)),Object target(對象),Exception ex);
?public void afterThrowing(Method method,Object[] args(目標(biāo)參數(shù)),Object target(對象),ServletException ex(其他類型的異常));
結(jié)論:異常通知(如上)方法參數(shù)里必須有異常,其他參數(shù)可有可無的。
拋出異常通知案例:
public class MoocThrowsAdvice implements ThrowsAdvice{
public void afterThrows(Exception ex){
System.out.println("拋出異常通知執(zhí)行了");
}
public void afterThrows(Method method,Object[] object,Object target,Exception ex){
System.out.println("拋出異常通知執(zhí)行了");
}
}
四、After Returning advice
1、返回后通知必須實(shí)現(xiàn)org.springframework.aop.AfterReturningAdvice接口(它和基于配置文件的配置方式是一樣的)
2、可以訪問返回值(但不能修改返回值)、被調(diào)用的方法、方法的參數(shù)和目標(biāo)。
3、如果拋出異常,將會拋出攔截器鏈,替代返回值。
返回后通知案例
public class MoocAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("返回后通知方法執(zhí)行了"+method.getName()+" ?"+target.getClass().getName()+" ?"+returnValue);
}
}
五、Interception around advice(環(huán)繞通知)
1、Spring的切入點(diǎn)模型使得切入點(diǎn)可以獨(dú)立與advice重用,以針對不同的advice可以使用相同的切入點(diǎn)(和之前基于XML配置文件的AOP實(shí)現(xiàn)方式是一樣的,切入點(diǎn)可以放在外面單獨(dú)地去定義,通過Point reference,在每一個業(yè)務(wù)邏輯方法中都可以引用相同的切入點(diǎn),當(dāng)然,每個Advice也可以定義自己的Point cut)。
案例:
public class MoocMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object obj = null;
System.out.println("環(huán)繞前通知實(shí)現(xiàn)了");
obj = invocation.proceed();
System.out.println("環(huán)繞后通知實(shí)現(xiàn)了");
return null;
}
}
六、Introduction advice(和XML配置中的Introduction advice一樣的功能)
1、Spring把引入通知作為一種特殊的攔截通知。
2、如果使用API實(shí)現(xiàn)AOP,則需要IntroductionAdvisor和IntroductionInterceptor這兩個接口。
3、Introduction advice僅適用于類,不能和任何其它切入點(diǎn)一起使用。
如下為基于XML配置的Introduction advice內(nèi)容
一個Spring test suite的例子
1、如果調(diào)用lock()方法,希望所有的setter方法拋出LockedException異常(使用場景:如使物體不可變,AOP典型例子)
2、需要完成繁重任務(wù)的IntroductionInterceptor,不是去實(shí)現(xiàn)該接口,而是使用org.springframework.aop.support.DelegatingIntroductionInterceptor
查看全部 -
Spring Bean裝配之Bean的生命周期
1、Bean的定義:XML文件中的<bean>標(biāo)簽的配置。
2、Bean的初始化:IOC容器(ApplicationContext)加載配置文件,并生成Bean的實(shí)例。
3、Bean的使用:通過getBean()方法獲得Bean的實(shí)例,并使用Bean。
4、Bean的銷毀:在IOC容器銷毀前,銷毀所有由該容器創(chuàng)建的Bean的實(shí)例。
Bean的初始化和銷毀(針對某一個Bean)
Bean的初始化(兩種方式):
1、實(shí)現(xiàn)org.springframework.beans.factory.InitializingBean接口,覆蓋afterPropertiesSet方法。
2、配置<bean>標(biāo)簽時,添加init-method屬性。
Bean的銷毀(兩種方式)
1、實(shí)現(xiàn)org.springframework.beans.factory.DisposableBean接口,覆蓋destroy方法(比如:釋放一些連接池)。
2、配置<bean>標(biāo)簽的destroy-method屬性。
Bean的初始化和銷毀(針對所有Bean,在XML配置文件的描述中添加default-init-method="init",default-destroy-method="destroy",注意:默認(rèn)的初始化配置屬性,當(dāng)Bean里沒有該方法時,也不會報錯)
注意:當(dāng)同時使用Bean的屬性配置、實(shí)現(xiàn)接口的配置,會先執(zhí)行實(shí)現(xiàn)接口初始化和銷毀方式、再執(zhí)行配置初始化和銷毀方式,默認(rèn)屬性配置不會生效,也就是說一個Bean沒使用init-method屬性和實(shí)現(xiàn)接口,那么這個默認(rèn)屬性配置則可以使用。
查看全部 -
Spring Bean裝配之Bean的配置項(xiàng)及作用域
Bean的常用配置項(xiàng)(包括這些配置的含義和作用)
Id:整個IOC容器中Bean的唯一標(biāo)識。
Class:具體實(shí)現(xiàn)的哪一個類,這里為類的路徑(理論上只配置Class即可)。
Scope:Bean的作用域。
Constructor arguments:構(gòu)造器的參數(shù)。
Properties:屬性。
Autowiring mode:自動裝配的模式。
lazy-initialization mode:懶加載模式。
Initialization/destruction method:初始化和銷毀方法。
從IOC容器中獲取對象的兩種方式:
1、通過Id來獲取,必須配置Id。
2、通過Bean的類型來獲取,只配置Class即可。
Bean的作用域
singleton:單例,指一個IOC容器(ApplicationContext)中只存在一個標(biāo)識singleton的對象(默認(rèn)為單例模式)。
prototype:每次請求(通過getBean()方法)創(chuàng)建一個實(shí)例的時候,都會獲得一個不同的對象,destroy方式不生效(請求完成后,這個實(shí)例也就不會再使用了,會被垃圾回收器回收)。
request:每次http請求創(chuàng)建一個實(shí)例,僅在當(dāng)前的request內(nèi)有效(request范圍內(nèi),向IOC容器中獲取這個對象,都是同一個實(shí)例,當(dāng)有另一個的request請求,則會創(chuàng)建一個新的實(shí)例)。
session:同上,每次http請求創(chuàng)建,當(dāng)前session內(nèi)有效。
global session:基于portlet的web中有效(Spring對portlet也提供了支持),如果在單獨(dú)的web應(yīng)用中,golbal session和session作用域一樣。
portlet定義了global session擴(kuò)展:portlet更多做應(yīng)用的集成,比如ON系統(tǒng)、HR系統(tǒng)、財務(wù)系統(tǒng)等等,通常在一個企業(yè)內(nèi)部,不會每一個系統(tǒng)都去進(jìn)行登錄,所以就會使用porlet,把每一個常用的功能都列在里面,做成一個單點(diǎn)登錄,點(diǎn)擊相應(yīng)任一區(qū)域或鏈接,跳到相應(yīng)系統(tǒng)中,這其實(shí)就是兩個系統(tǒng)兩個Web應(yīng)用了,所以這一定不會是一個session,所以global session就是指這種情況下session的作用范圍。
Spring官網(wǎng)對作用域的解釋
Bean的生命周期
Bean的自動裝配
Resource和ResourceLoader(IOC加載資源文件(Spring的XML配置文件)用到的類,也可以加載其他資源文件)
查看全部 -
Spring Bean裝配之Spring對JSR支持的說明
1:Spring支持使用JSR-250@Resource注解,通常用于成員變量和set方法上,這是一種在JavaEE5和6的通用模式(當(dāng)然7也是支持的),Spring對對象的管理也支持這種方式。
2:@Resource有一個name屬性,并且Spring默認(rèn)把該name作為被注入bean的名稱(如果沒有顯示指定name屬性,默認(rèn)名稱是屬性名或者set方法名,默認(rèn)是根據(jù)注解的位置)。
3:注解提供的名字被解析為一個Bean的名稱(@Resource的name屬性),這個過程是由ApplicationContext中的CommonAnnotationBeanPostProcessor發(fā)現(xiàn)并處理的。
@PostConstruct和@PreDestroy
1:CommonAnnotationBeanPostProcessor不僅能識別JSR-250中的生命周期注解@Resource,在Spring2.5中引入支持初始化回調(diào)和銷毀回調(diào),前提是CommonAnnotationBeanPostProcessor這個類已經(jīng)在Spring的ApplicationContext中注冊了。(只有CommonAnnotationBeanPostProcessor類在IOC容器中注冊了,才能處理@Resource,@PostConstruct,@PreDestroy)。
注意:自動注入,用Map<String,Object>map盛放所有的容器中的bean,然后循環(huán)打印所有的bean所屬的類就能看到這個類了org.springframework.context.annotation.CommonAnnotationBeanPostProcessor,有這個類的bean。
@PostConstruct和@PreDestroy:這兩個注解一般在的方法上,在初始化Bean和銷毀之前,都會去調(diào)用這兩個注解下的方法。
案例:(@Resource案例)
步驟1:
@Component
public class JsrDao {
public void print(){
System.out.println("JsrDao的方法執(zhí)行了");
}
}
@Component
public class JsrService {
// @Resource
private JsrDao jsrDao;
public void print(){
jsrDao.print();
}
@Resource
public void setJsrDao(JsrDao jsrDao) {
this.jsrDao = jsrDao;
}
}
步驟2:
@Configuration
@ComponentScan
public class JsrConfig {
}
測試:
public class TestJsr {
@Test
public void testJsr(){
ApplicationContext ac=new AnnotationConfigApplicationContext(JsrConfig.class);
JsrService js=ac.getBean("jsrService",JsrService.class);
js.print();
}
}
結(jié)果:JsrDao的方法執(zhí)行了
知識拓展:
@Resource和@Autowired都是做bean的注入時使用,其實(shí)@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要導(dǎo)入,但是Spring支持該注解的注入。
1、共同點(diǎn)
兩者都可以寫在字段和setter方法上。兩者如果都寫在字段上,那么就不需要再寫setter方法。
2、不同點(diǎn)
(1)@Autowired
@Autowired為Spring提供的注解,需要導(dǎo)入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
public?class?TestServiceImpl?{????//?下面兩種@Autowired只要使用一種即可????@Autowired????private?UserDao?userDao;?//?用于字段上?????????@Autowired????public?void?setUserDao(UserDao?userDao)?{?//?用于屬性的方法上?????????this.userDao?=?userDao;?????}?}
@Autowired注解是按照類型(byType)裝配依賴對象,默認(rèn)情況下它要求依賴對象必須存在,如果允許null值,可以設(shè)置它的required屬性為false。如果我們想使用按照名稱(byName)來裝配,可以結(jié)合@Qualifier注解一起使用。如下:
public?class?TestServiceImpl?{?????@Autowired?????@Qualifier("userDao")????private?UserDao?userDao;??}
(2)@Resource
@Resource默認(rèn)按照ByName自動注入,由J2EE提供,需要導(dǎo)入包javax.annotation.Resource。@Resource有兩個重要的屬性:name和type,而Spring將@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以,如果使用name屬性,則使用byName的自動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不制定name也不制定type屬性,這時將通過反射機(jī)制使用byName自動注入策略。
public?class?TestServiceImpl?{????//?下面兩種@Resource只要使用一種即可?????@Resource(name="userDao")????private?UserDao?userDao;?//?用于字段上?????????@Resource(name="userDao")????public?void?setUserDao(UserDao?userDao)?{?//?用于屬性的setter方法上?????????this.userDao?=?userDao;?????}?}
注:最好是將@Resource放在setter方法上,因?yàn)檫@樣更符合面向?qū)ο蟮乃枷?,通過set、get去操作屬性,而不是直接去操作屬性。
@Resource裝配順序:
①如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進(jìn)行裝配,找不到則拋出異常。
②如果指定了name,則從上下文中查找名稱(id)匹配的bean進(jìn)行裝配,找不到則拋出異常。
③如果指定了type,則從上下文中找到類似匹配的唯一bean進(jìn)行裝配,找不到或是找到多個,都會拋出異常。
④如果既沒有指定name,又沒有指定type,則自動按照byName方式進(jìn)行裝配;如果沒有匹配,則回退為一個原始類型進(jìn)行匹配,如果匹配則自動裝配。
@Resource的作用相當(dāng)于@Autowired,只不過@Autowired按照byType自動注入。
@PostConstruct和@PreDestroy(和以上案例相似,主要增加兩個方法,并關(guān)閉Spring上下文)
@Component
public class JsrService {
@Resource
private JsrDao jsrDao;
public void print(){
jsrDao.print();
}
public void setJsrDao(JsrDao jsrDao) {
this.jsrDao = jsrDao;
}
@PostConstruct
public void jsrInit(){
System.out.println("Bean初始化方法執(zhí)行了");
}
@PreDestroy
public void jsrDestroy(){
System.out.println("Bean銷毀方法執(zhí)行了");
}
}
測試:@Test
public void testJsr(){
AbstractApplicationContext ac=new AnnotationConfigApplicationContext(JsrConfig.class);
JsrService js=ac.getBean("jsrService",JsrService.class);
js.print();
ac.close();
}
結(jié)果:(和XML文件配置的init-method和destroy-method一樣的功能)
Bean初始化方法執(zhí)行了
JsrDao的方法執(zhí)行了
Bean銷毀方法執(zhí)行了
使用JSR330標(biāo)準(zhǔn)注解
1:從Spring3.0開始支持JSR330標(biāo)準(zhǔn)注解(依賴注入注解),其掃描方式與Spring注解一致。
2:使用JSR330需要依賴javax.inject包。
3:使用Maven引入方式如下。
@Inject注解:等效于@Autowired,可以使用于類、屬性、方法、構(gòu)造器上。
@Named注解:使用特定名稱進(jìn)行依賴注入,與@Qualifier是等效的,還可以注解在類上,相當(dāng)于@Component。(同一種類型的Bean在IOC容器中有多個時候,可以使用@Named指定特定的Bean)
在方法上:
在類上:
案例:@Inject和@Named
把@Componet換成@Named,@Resource換成Inject,執(zhí)行結(jié)果相同。
查看全部
舉報