Spring通過註解配置bean
簡介及測試
Spring支援通過註解的方式來配置bean例項。Spring能夠從classpath下自動掃描,偵測和例項化具有特定註解的元件。特定元件包括:
@Component:基本註解,標識了一個受Spring管理的元件。
@Repository:標識持久層元件。
@Service:標識服務車(業務層)元件。
@Controller:標識表現層元件。
現在模擬一下基本的MVC的呼叫關係,首先分別建立dao層,service層和controller層的元件:
public interface UserDao {
public void save();
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDao save...");
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void save(){
System.out.println("UserService save..." );
userDao.save();
}
}
@Controller
public class UserAction {
@Autowired
private UserService userService;
public void save(){
System.out.println("UserAction save...");
userService.save();
}
}
對於掃描到的元件,Spring有預設的命名策略:使用非限定類名第一個字母小寫的形式命名。也可以在註解中通過value屬性值標識元件的名稱,其中value是預設屬性,可以直接以字串的形式為註解的value屬性賦值,例如在上述程式碼中,我們通過@Repository(“userDao”)的形式將UserDaoImpl例項命名為userDao。
當在元件類上使用了特點的註解之後,還需要在Spring的配置檔案中宣告<context:component-scan>:(在這裡,我的所有要被掃描的元件類都在包com.MySpring.annotation下)
beans-annotation.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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 宣告需要掃描的包 -->
<!-- 其中base-package屬性指定需要掃描的基類包,spring容器將會掃描這個基類包及其子包中的所有類 -->
<!-- 當需要掃描多個包時,可以使用逗號分隔 -->
<context:component-scan base-package="com.MySpring.annotation"></context:component-scan>
</beans>
另外,<context:component-scan>元素還會自動註冊AutowireAnnotationBeanPostProcessor例項,該例項可以自動裝配具有@Autowired,@Resource,@Inject註解的屬性。(通常都使用@Autowired)
編寫測試類:
public class Test {
@org.junit.Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml");
UserAction userAction = (UserAction) ctx.getBean("userAction");
userAction.save();
}
}
如果報錯如下:
java.lang.NoClassDefFoundError:org/springframework/aop/TargetSource
新增對應spring版本的aop jar包即可,例如我新增的是spring-aop-4.0.0.RELEASE.jar。然後即可成功執行:
關於<context:component-scan>節點
(1). 屬性resource-pattern可以指定掃描基包下特定的類,而非所有類,例如:
<context:component-scan
base-package="com.MySpring.annotation"
resource-pattern="autowire/*.java"></context:component-scan>
(2). <context:include-filter>和<context:exclude-filter>子節點分別指明基類包下要包含的目標類和不包含的目標類,其屬性如下:(前兩個比較常用)
關於@Autowired
@Autowired註解自動裝配具有相容型別的單個bean屬性。
預設情況下,所有使用@Autowired註解的屬性都需要設定,當Spring找不到匹配的bean裝配屬性時,會丟擲異常。若某一屬性允許不被設定,可以設定@Autowired註解的required屬性為false。
預設情況下,當IOC容器裡存在多個型別相容的bean時(例如現在UserDao介面有兩個實現類,UserDaoImpl只是其一),通過型別的自動裝配將無法工作。有兩種解決方式,一種是像上述例子中一樣,通過@Repository(“userDao”)設定UserDaoImpl例項的名稱為userDao,然後在UserService中宣告UserDao元件名為userDao即可。第二種方式是在裝配屬性上使用@Qualifier註解進行設定,例如在UserService中做如下設定:
@Autowired
@Qualifier("userDaoImpl")
private UserDao userDao;
就會載入UserDaoImpl這個實現類的例項。