用註解來向Spring容器註冊Bean。需要在applicationContext.xml中註冊<context:component-scan base-package=”pagkage1[,pagkage2,…,pagkageN]”/>。
如:在base-package指明一個包
<context:component-scan base-package="cn.gacl.java"/>
表明cn.gacl.java包及其子包中,如果某個類的頭上帶有特定的註解【@Component/@Repository/@Service/@Controller】,就會將這個對象作爲Bean註冊進Spring容器。也可以在<context:component-scan base-package=” ”/>中指定多個包,如:
<context:component-scan base-package="cn.gacl.dao.impl,cn.gacl.service.impl,cn.gacl.action"/>
多個包逗號隔開。
一、基於@Component註解的配置
spring 2.5 中除了提供 @Component 註釋外,還定義了幾個擁有特殊語義的註釋,它們分別是:@Repository、@Service
和 @Controller。
在目前的 Spring 版本中,這 3 個註釋和 @Component 是等效的,但是從註釋類的命名上,很容易看出這 3 個註釋分別和持久層、業務層和控制層(Web 層)相對應。
雖然目前這3 個註釋和 @Component 相比沒有什麼新意,但 Spring 將在以後的版本中爲它們添加特殊的功能。所以,如果 Web 應用程序採用了經典的三層分層結構的話,最好在持久層、業務層和控制層分別採用上述註解對分層中的類進行註釋。
1、@controller 控制器(注入服務)
2、@service 服務(注入dao)
4、@component (把普通pojo實例化到spring容器中,相當於配置文件中的<bean id="" class=""/>)
@component用法如下:
- @Component("userDao")
- public class UserDaoImp implements UserDao{
- @Override
- public void add(User user) {
- System.out.println(user.getName());
- System.out.println(user.getSex());
- System.out.println(user.getAge());
- }
- }
@Component("userDao")
public class UserDaoImp implements UserDao{
@Override
public void add(User user) {
System.out.println(user.getName());
System.out.println(user.getSex());
System.out.println(user.getAge());
}
}
在類上使用@Component註解,表示該類定義爲Spring管理Bean,使用默認value(可選)屬性表示Bean標識符。
相當於:
- <bean id="userDao" class="com.mucfc.dao.UserDao"/>
<bean id="userDao" class="com.mucfc.dao.UserDao"/>
@Component,@Service,@Controller,@Repository註解的類,並把這些類納入進spring容器中管理。下面寫這個是引入component的掃描組件
- <!-- 配置的bean所在包的位置 -->
- lt;context:component-scan base-package="com.mucfc" />
<!-- 配置的bean所在包的位置 -->
<context:component-scan base-package="com.mucfc" />
其中base-package爲需要掃描的包(含所有子包) @Component泛指組件,當組件不好歸類的時候,我們可以使用這個註解進行標註。
二、使用實例
User.Java:用@Repository註解
- package com.mucfc.model;
- import org.springframework.context.annotation.Scope;
- import org.springframework.stereotype.Repository;
- @Repository("user")
- @Scope("prototype")
- //@Repository用於標註數據訪問組件,即DAO組件
- //@Scope("prototype")讓其每次返回不同的實例,默認是單例
- public class User {
- private String name;
- private String sex;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- private int age;
- }
package com.mucfc.model;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository("user")
@Scope("prototype")
//@Repository用於標註數據訪問組件,即DAO組件
//@Scope("prototype")讓其每次返回不同的實例,默認是單例
public class User {
private String name;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
}
UserDao.java- package com.mucfc.dao;
- import com.mucfc.model.User;
- public interface UserDao {
- public void add(User user);
- }
package com.mucfc.dao;
import com.mucfc.model.User;
public interface UserDao {
public void add(User user);
}
UserDaoImp.java:用@Controller註解- package com.mucfc.daoimp;
- import org.springframework.stereotype.Controller;
- import com.mucfc.dao.UserDao;
- import com.mucfc.model.User;
- @Controller("userDao")
- //@Controller用於標註控制層組件
- public class UserDaoImp implements UserDao{
- @Override
- public void add(User user) {
- System.out.println(user.getName());
- System.out.println(user.getSex());
- System.out.println(user.getAge());
- }
- }
package com.mucfc.daoimp;
import org.springframework.stereotype.Controller;
import com.mucfc.dao.UserDao;
import com.mucfc.model.User;
@Controller("userDao")
//@Controller用於標註控制層組件
public class UserDaoImp implements UserDao{
@Override
public void add(User user) {
System.out.println(user.getName());
System.out.println(user.getSex());
System.out.println(user.getAge());
}
}
@Controller對應表現層的Bean,也就是Action,例如:
1 @Controller
2 @Scope("prototype")
3 public class UserAction extends BaseAction<User>{
4 ……
5 }
使用@Controller註解標識UserAction之後,就表示要把UserAction交給Spring容器管理,在Spring容器中會存在一個名字爲"userAction"的action,這個名字是根據UserAction類名來取的。注意:如果@Controller不指定其value【@Controller】,則默認的bean名字爲這個類的類名首字母小寫,如果指定value【@Controller(value="UserAction")】或者【@Controller("UserAction")】,則使用value作爲bean的名字。
這裏的UserAction還使用了@Scope註解,@Scope("prototype")表示將Action的範圍聲明爲原型,可以利用容器的scope="prototype"來保證每一個請求有一個單獨的Action來處理,避免struts中Action的線程安全問題。spring 默認scope 是單例模式(scope="singleton"),這樣只會創建一個Action對象,每次訪問都是同一Action對象,數據不安全,struts2 是要求每次次訪問都對應不同的Action,scope="prototype" 可以保證當有請求的時候都創建一個Action對象
- package com.mucfc.service;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Service;
- import com.mucfc.dao.UserDao;
- import com.mucfc.model.User;
- @Service("userService")
- //@Service用於標註業務層組件
- public class UserService {
- //setter注入接口、面向接口編程
- private UserDao userdao ;
- public void add(User user){
- userdao.add(user) ;
- }
- public UserDao getUserdao() {
- return userdao;
- }
- //註解
- @Resource(name="userDao")
- public void setUserdao(UserDao userdao) {
- this.userdao = userdao;
- }
- }
package com.mucfc.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.mucfc.dao.UserDao;
import com.mucfc.model.User;
@Service("userService")
//@Service用於標註業務層組件
public class UserService {
//setter注入接口、面向接口編程
private UserDao userdao ;
public void add(User user){
userdao.add(user) ;
}
public UserDao getUserdao() {
return userdao;
}
//註解
@Resource(name="userDao")
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
}
注意:在Action聲明的“userService”變量的類型必須是“UserServiceImpl”或者是其父類“UserService”,否則由於類型不一致而無法注入,由於Action中的聲明的“userService”變量使用了@Resource註解去標註,並且指明瞭其name = "userService",這就等於告訴Spring,說我Action要實例化一個“userService”,你Spring快點幫我實例化好,然後給我,當Spring看到userService變量上的@Resource的註解時,根據其指明的name屬性可以知道,Action中需要用到一個UserServiceImpl的實例,此時Spring就會把自己創建好的名字叫做"userService"的UserServiceImpl的實例注入給Action中的“userService”變量,幫助Action完成userService的實例化,這樣在Action中就不用通過“UserService
userService = new UserServiceImpl();”這種最原始的方式去實例化userService了。如果沒有Spring,那麼當Action需要使用UserServiceImpl時,必須通過“UserService userService = new UserServiceImpl();”主動去創建實例對象,但使用了Spring之後,Action要使用UserServiceImpl時,就不用主動去創建UserServiceImpl的實例了,創建UserServiceImpl實例已經交給Spring來做了,Spring把創建好的UserServiceImpl實例給Action,Action拿到就可以直接用了。Action由原來的主動創建UserServiceImpl實例後就可以馬上使用,變成了被動等待由Spring創建好UserServiceImpl實例之後再注入給Action,Action才能夠使用。這說明Action對“UserServiceImpl”類的“控制權”已經被“反轉”了,原來主動權在自己手上,自己要使用“UserServiceImpl”類的實例,自己主動去new一個出來馬上就可以使用了,但現在自己不能主動去new“UserServiceImpl”類的實例,new“UserServiceImpl”類的實例的權力已經被Spring拿走了,只有Spring才能夠new“UserServiceImpl”類的實例,而Action只能等Spring創建好“UserServiceImpl”類的實例後,再“懇求”Spring把創建好的“UserServiceImpl”類的實例給他,這樣他才能夠使用“UserServiceImpl”,這就是Spring核心思想“控制反轉”,也叫“依賴注入”,“依賴注入”也很好理解,Action需要使用UserServiceImpl幹活,那麼就是對UserServiceImpl產生了依賴,Spring把Acion需要依賴的UserServiceImpl注入(也就是“給”)給Action,這就是所謂的“依賴注入”。對Action而言,Action依賴什麼東西,就請求Spring注入給他,對Spring而言,Action需要什麼,Spring就主動注入給他。beans.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:p="http://www.springframework.org/schema/p"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd">
- <!-- 配置的bean所在包的位置 -->
- <context:component-scan base-package="com.mucfc" />
- </beans>
- package com.mucfc.anno;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import com.mucfc.model.User;
- import com.mucfc.service.UserService;
- public class Test {
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
- UserService service=(UserService)applicationContext.getBean("userService");
- User user1 = (User) applicationContext.getBean("user");
- User user2 = (User) applicationContext.getBean("user");
- user1.setName("小明");
- user1.setSex("男");
- user1.setAge(22);
- user2.setName("小紅");
- user2.setSex("女");
- user2.setAge(18);
- service.add(user1);
- service.add(user2);
- }
- }
package com.mucfc.anno;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mucfc.model.User;
import com.mucfc.service.UserService;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService service=(UserService)applicationContext.getBean("userService");
User user1 = (User) applicationContext.getBean("user");
User user2 = (User) applicationContext.getBean("user");
user1.setName("小明");
user1.setSex("男");
user1.setAge(22);
user2.setName("小紅");
user2.setSex("女");
user2.setAge(18);
service.add(user1);
service.add(user2);
}
}
結果:
當在組件類中使用了特定的註解之後,還需要在Spring的配置文件中聲明 <context:component-scan>:
- base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描整個基類包裏及其子包中的所有類
- 當需要掃描多個包時,可以使用逗號分隔
- 如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類,實例:
- <context:include-filter>子節點表示要包含的目標類
- <context:exclude-filter>子節點表示要排除在外的目標類
- <context:component-scan>下可以擁有若干個<context:include-filter>和<context:exclude-filter>子節點
- <context:include-filter>和<context:exclude-filter>子節點支持多種類型的過濾表