繼前幾章所講解的注解中:
http://www.cnblogs.com/EasonJim/p/6892280.html
http://www.cnblogs.com/EasonJim/p/6899747.html
http://www.cnblogs.com/EasonJim/p/6901115.html
發現上述遺漏了一些注解,比如:@Repository、@Service、@Controller、@Component,現在做如下補充:
Spring自2.0版本開始,陸續引入了一些注解用於簡化Spring的開發。到了2.5版本時才大量引入更全面的注解功能。@Repository注解便屬於最先引入的一批,它用於將數據訪問層(DAO 層)的類標識為Spring Bean。具體只需將該注解標注在DAO類上即可。同時,為了讓Spring能夠掃描類路徑中的類並識別出@Repository注解,需要在XML配置文件中啟用Bean的自動掃描功能,這可以通過<context:component-scan/>實現。如下所示:
//首先使用 @Repository 將 DAO 類聲明為 Bean package com.jsoft.dao; @Repository public class UserDaoImpl implements UserDao{ …… }
<!--其次,在XML配置文件中啟動Spring的自動掃描功能--> <beans … > …… <context:component-scan base-package=”com.jsoft.dao” /> …… </beans>
如此,我們就不再需要在XML中顯式使用<bean/>進行Bean的配置。Spring在容器初始化時將自動掃描base-package指定的包及其子包下的所有class文件,所有標注了@Repository的類都將被注冊為Spring Bean。
為什么@Repository只能標注在DAO類上呢?這是因為該注解的作用不只是將類識別為Bean,同時它還能將所標注的類中拋出的數據訪問異常封裝為Spring的數據訪問異常類型。Spring本身提供了一個豐富的並且是與具體的數據訪問技術無關的數據訪問異常結構,用於封裝不同的持久層框架拋出的異常,使得異常獨立於底層的框架。
Spring 2.5在@Repository的基礎上增加了功能類似的額外三個注解:@Component、@Service、@Constroller,它們分別用於軟件系統的不同層次:
- @Component是一個泛化的概念,僅僅表示一個組件 (Bean) ,可以作用在任何層次。
- @Service通常作用在業務層,但是目前該功能與@Component相同。
- @Constroller通常作用在控制層,但是目前該功能與@Component相同。
通過在類上使用@Repository、@Component、@Service和@Constroller注解,Spring會自動創建相應的BeanDefinition對象,並注冊到ApplicationContext中。這些類就成了Spring受管組件。這三個注解除了作用於不同軟件層次的類,其使用方式與@Repository是完全相同的。
另外,除了上面的四個注解外,用戶可以創建自定義的注解,然后在注解上標注@Component,那么,該自定義注解便具有了與所@Component相同的功能。不過這個功能並不常用。
當一個Bean被自動檢測到時,會根據那個掃描器的BeanNameGenerator策略生成它的Bean名稱。默認情況下,對於包含name屬性的@Component、@Repository、 @Service和@Controller,會把name取值作為Bean的名字。如果這個注解不包含name值或是其他被自定義過濾器發現的組件,默認Bean名稱會是小寫開頭的非限定類名。如果你不想使用默認Bean命名策略,可以提供一個自定義的命名策略。首先實現BeanNameGenerator接口,確認包含了一個默認的無參數構造方法。然后在配置掃描器時提供一個全限定類名,如下所示:
<beans ...> <context:component-scan base-package="a.b" name-generator="a.SimpleNameGenerator"/> </beans>
與通過XML配置的Spring Bean一樣,通過上述注解標識的Bean,其默認作用域是"singleton"(單例),為了配合這四個注解,在標注Bean的同時能夠指定Bean的作用域,Spring2.5引入了@Scope注解。使用該注解時只需提供作用域的名稱就行了,如下所示:
@Scope("prototype")
@Repository
public class Demo { … }
如果你想提供一個自定義的作用域解析策略而不使用基於注解的方法,只需實現ScopeMetadataResolver接口,確認包含一個默認的沒有參數的構造方法。然后在配置掃描器時提供全限定類名:
<context:component-scan base-package="a.b" scope-resolver="a.SimpleScopeResolver" />
簡單例子:
DAO層
package com.jsoft.dao; public interface UserDao { public void save(); }
DAO層實現類
package com.jsoft.dao.impl; import org.springframework.stereotype.Repository; import com.jsoft.dao.UserDao; @Repository public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("測試保存"); } }
Service層
package com.jsoft.service; public interface UserService { public void Usersave(); }
Service實現類
package com.jsoft.service.Impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.jsoft.dao.UserDao; import com.jsoft.service.UserService; @Service public class UserServiceImpl implements UserService{ @Autowired//自動注入 UserDao userDao; @Override public void Usersave() { System.out.println("Service執行保存方法"); userDao.save(); } }
DTO中間類
package com.jsoft.dto; import org.springframework.stereotype.Component; @Component public class DtoClass { public void say(){ System.out.println("我是DTO"); } }
控制層
package com.jsoft.Controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import com.jsoft.dto.DtoClass; import com.jsoft.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @Autowired public DtoClass dtoClass; public void save(){ System.out.println("控制層save"); dtoClass.say(); userService.Usersave(); } }
測試類
package com.jsoft.test.autoTest; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import com.jsoft.Controller.UserController; import com.jsoft.util.SpringUtil; public class MyTest { ApplicationContext applicationContext = null; @Before public void before() { applicationContext = SpringUtil.getApplicationContext(); } @Test public void controller(){ UserController controller = applicationContext.getBean(UserController.class); controller.save(); } }
參考:
