Spring中三種配置Bean的方式分別是:
- 基於XML的配置方式
- 基於注解的配置方式
- 基於Java類的配置方式
一.基於XML的配置
這個很簡單,所以如何使用就略掉。
二.基於注解的配置
Spring2.0開始引入基於注解的配置方式,即Bean的定義信息可以通過在Bean的實現類上標注注解實現。
不清楚Java注解的參閱Java注解基本原理
@Component是Spring容器中的基本注解,表示容器中的一個組件(bean),可以作用在任何層次,下面的示例介紹該注解的使用方法。
注解配置示例:
@Component("userDao") public class userDao{......}
等效於XML配置
<bean id="userDao" class="cn.lovepi.***.userDao"/>
此外,還有一些其他的可以被用來注解bean的注解,這些可以讓注解類本身的用途更加清晰,此外,特定的注解也具備特定的功能。
Spring在2.5后提供了一個context的命名空間,它提供了通過掃描類包來加載利用注解定義的Bean的方式。
在context中可以使用resource-pattern來過濾出特定的類。
<context:component-scan base-package="cn.lovepi.spring" resource-pattern="anno/*.class"/>
默認情況下加載的是package下的*.class即掃描全部類,在使用了resource-pattern之后,則只掃描package下的anno子包下的所有類。
不過使用resource-pattern並不能提供給我們完善的功能,所以我們得使用過濾子元素的方法。
<context:component-scan base-package="cn.lovepi.spring"> <context:include-filter type="regex" expression="cn.lovepi.spring.*"/> <context:exclude-filter type="aspectj" expression="cn.lovepi..*Controller+"/> </context:component-scan>
其中:
include-filter表示要包含的目標類,
exclude-filter表示要排除在外的目標類
一個component-scan標簽下可以有多個include-filter和exclude-filter,
過濾表達式所支持的類型如下表所示:
在這些類型當中,除了Custom外,aspectj的過濾功能最強大,他能輕易的實現其他類別的過濾規則。
Spring3.0提供了一系列的針對依賴注入的注解,這使得Spring IoC在XML文件之外多了一種可行的選擇,主要包含如下注解類型:
- Bean的定義注解
- Bean的生命周期注解
- Bean的依賴檢查注解
- Bean的自動裝配注解
1.Bean的定義注解
Spring自2.0開始,陸續引入了一些注解用於簡化Spring的開發。
@Repository注解便屬於最先引入的一批,用於將數據訪問層(DAO層)的類標識為Spring Bean。具體使用如下:
①首先使用@Repository將DAO類聲明為Bean
@Repository public class UserDaoImpl implements UserDao{......}
②在XML配置文件中啟動Spring的自動掃描功能
<beans ...> <context:component-scan base-package="cn.lovepi.dao"/> ...... <beans/>
如此的話,我們便不在需要在XML當中顯式使用bean來進行bean的配置。Spring容器在初始化的時候便會自動掃描base-package所指定的包以及子包下面的所有class文件。所有標注為Repository的類將被自動注冊為bean。
為什么Repository只能標注在DAO類上面呢?
因為該注解的作用不只是將類識別為bean,同時他還能將所標注的類中所拋出的數據訪問異常封裝為Spring的數據訪問異常類型。Spring本身提供了一個豐富的,並且是與具體的訪問技術無關的數據訪問異常結構,用於封裝不同的持久層框架所拋出的異常,使得異常獨立與底層的框架。
Spring2.5在@Repository的基礎上增加了功能類似的額外三個注解,總共有如下四種注解:
@Component:一個泛化的概念,表示一個組件(Bean),可作用在任何層次
@Controller:用於對Controller實現類進行標注,目前該功能與Component相同
@Repository:用於對DAO實現類進行標注
@Service:用於對Service實現類進行標注,目前該功能與Component相同
這三個注解除了作用於不同軟件層次的類,其使用方式與Repository是完全相同的。
2.Bean的生命周期注解
在某些情況下,可能需要我們手工做一些額外的初始化或者銷毀操作,例如資源的獲取和是否操作,Spring1.x為此提供了兩種方式供用戶指定執行生命周期回調的方法:
實現Spring提供的兩個接口:initializingBean 和 DisposableBean,這種方法是要求bean類實現Spring的接口,但增加了bean和Spring容器的耦合度,因此不推薦使用。
在XML文件中使用<bean>的init-method 和 destory-method 屬性,指定初始化之后和回調之前的回調方法。這兩個屬性的取值是bean中相應的初始化和銷毀方法的名稱。方法名稱任意,但是方法不能有參數。
示例如下:
<bean id="userService" class="cn.lovepi.***.UserService" init-method="init" destory-method="destory"> </bean>
在這里,我們指定了userService 這個bean的初始化方法為:init 銷毀方法為:destory
Spring2.5在保留以上兩種方式的基礎上,提供了對JSR-250的支持。
JSR-250規范定義了兩個用於指定聲明周期方法的注解:
@PostConstruct:初始化之后的執行的回調方法
@PreDestroy:銷毀之前的回調方法
注解示例說明:
public class PersonService{ @PostConstruct public void init(){......} @PreDestory public void destory(){......} }
在這里init方法是初始化之后執行的方法,而destory方法為銷毀之前執行的方法。
由於使用了注解,所以得激活Bean的后處理器,所以得在XML配置文件當中增加
<context:annotation-config/>
3.Bean的依賴檢查注解
Spring2.0之前使用dependency-check在配置文件中設置屬性用於依賴檢查(只會檢查Setter方法是否被調用),缺點是粒度較粗,該屬性的取值包括以下幾種:
- none: 默認不執行依賴檢查
- simple :對原始基本類型和集合類型進行檢查
- objects :對復雜類型進行檢查
- all :對所有類型進行檢查
使用Spring2.0提供的@Required注解,提供了更細粒度的控制,@Required注解只能標注在Setter方法之上,(標注在其他方法之上會被忽略 )用於檢查其是否被調用,當Setter方法未被調用的話會拋出異常。
由於使用了注解,所以得激活Bean的后處理器,所以得在XML配置文件當中增加
<context:annotation-config/>
4.Bean的自動裝配注解
@Autowired可以對成員變量、方法和構造函數進行標注,來完成自動裝配的工作,他根據類型進行自動裝配,如果需要按名稱進行裝配,則需要配合@Qualifier使用。
當標注了@Autowired的方法所需的類型在Spring容器中不存在的話會拋出異常
@Service public class LoginService{ @Autowired private LogDao logDao; }
如上面的例子所示,假如Spring容器中沒有LogDao這個bean的話便會拋出異常。
解決的辦法便是使用required=false屬性來標注
public class LoginService{ @Autowired(required=false) private LogDao LogDao; }
但是假如Spring當中存在多個所需類型的bean,那么便要使用@Qualifier注解來指定名稱。
public class LoginService{ @Autowired @Qualifier("userDao") private UserDao userDao; }
@Autowired 可以對類中集合類的變量或方法入參進行標注,此時會將容器中類型匹配的所有Bean都注入進來,如下所示:
public class loginService{ @Autowired(required=false) public List<Plugin> pligins; public List<Plugin> getPlugins(){ return plugins; } }
Spring會將容器中所有類型為Plugin的bean都注入到集合中去。
三.基於Java類的配置
基於Java類定義Bean配置元數據,其實就是通過Java類定義Spring配置元數據,且直接消除XML配置文件。
首先讓我們看一下基於Java類如何定義Bean配置元數據,具體步驟如下:
使用@Configuration注解需要作為配置的類,表示該類將定義Bean的元數據
使用@Bean注解相應的方法,該方法名默認就是Bean的名稱,該方法返回值就是Bean的對象。
AnnotationConfigApplicationContext或子類進行加載基於java類的配置。
接下來通過示例來演示下如何基於Java類來配置Spring
首先創建一個配置類
@Configuration public class ApplicationContextConfig { @Bean public String message() { return "hello"; } }
然后還需要一個測試類,來查看配置是否成功
public class ConfigurationTest { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationContextConfig.class); System.out.println(ctx.getBean("message")); } }
通過@Configuration注解的類將被作為配置類使用,表示在該類中將定義Bean配置元數據,且使用@Configuration注解的類本身也是一個Bean,使用方式如下所示:
@Configuration("ctxConfig") public class ApplicationContextConfig { …… }
其中Configuration中的參數值即為該bean的名稱。
通過@Bean注解配置類中的相應方法,則該方法名默認就是Bean名,該方法返回值就是Bean對象,並定義了Spring IoC容器如何實例化、自動裝配、初始化Bean邏輯,具體使用方法如下:
@Bean(name={}, autowire=Autowire.NO, initMethod="", destroyMethod="")
其中name為bean的名稱,可以有多個,autowire為是否自動裝配,默認值為NO,initMethod為bean的初始化方法,destoryMethod為bean的銷毀方法。
bean的注解具體使用如下:
@Bean public String message() { return new String("hello"); }
如上的代碼等價與XML配置:
<bean id="message" class="java.lang.String"> <constructor-arg index="0" value="hello"/> </bean>
注意:使用bean注解的方法不能是private、final、static的。
基於Java方式的配置方式不是為了完全替代基於XML方式的配置,兩者可以結合使用,因此可以有兩種結合使用方式:
在基於Java方式的配置類中引入基於XML方式的配置文件
在基於XML方式的配置文件中中引入基於Java方式的配置
引入基於XML配置文件:
<bean id="message" class="java.lang.String"> <constructor-arg index="0" value="test"></constructor-arg> </bean>
@Configuration("ctxConfig") @ImportResource("classpath:com/jike/***/appCtx.xml") public class ApplicationContextConfig { …… }
可以看到在java程序中使用@ImportResource導入了XML的配置文件
引入基於Java的配置文件:
<context:annotation-config/> <bean id="ctxConfig" class=“com.jike.***..ApplicationContextConfig"/>
//測試類 public void testXmlConfig() { String configLocations[] = {" classpath:com/jike/***/appCtx.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations); …… }
可以看到在XML的配置文件當中將java的配置類當中Bean來聲明,第一行的是開啟注解驅動支持。
值得注意的是必須得配置<context:annotation-config/>在XML配置文件中。
Spring提供了一個AnnotationConfigApplicanContext類,能夠直接通過標注@Configuration的Java類啟動Spring容器:
通過構造函數加載配置類:
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class);
通過編碼方式注冊配置類:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(DaoConfig.class); ctx.register(ServiceConfig.class); ctx.refresh();
可以看到ctx注冊了多個configuration類,然后通過refresh類來刷新容器以應用這些配置文件。
可以通過代碼一個個的引入配置類,當然也可以使用@Import注解來引入配置類
引入多個配置類:
@Configuration @Import(DaoConfig.class) public class ServiceConfig {……}