自動化配置
例如我有一個 UserService,我希望在自動化掃描時,這個類能夠自動註冊到 Spring
容器中去,那麼可以給該類新增一個 @Service,作為一個標記。
和 @Service 註解功能類似的註解,一共有四個:
- @Component
- @Repository
- @Service
- @Controller
這四個中,另外三個都是基於 @Component
做出來的,而且從目前的原始碼來看,功能也是一致的,那麼為什麼要搞三個呢?主要是為了在不同的類上面新增時方便。
- 在 Service 層上,添加註解時,使用 @Service
- 在 Dao 層,添加註解時,使用 @Repository
- 在 Controller 層,添加註解時,使用 @Controller
- 在其他元件上添加註解時,使用 @Component
@Service
public class UserService {
public List<String> getAllUser() {
List<String> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add("javaboy:" + i);
}
return users;
}
}
新增完成後,自動化掃描有兩種方式,一種就是通過 Java 程式碼配置自動化掃描,另一種則是通過 xml 檔案來配置自動化掃描。
java程式碼配置自動掃描
@Configuration
@ComponentScan(basePackages = "org.javaboy.javaconfig.service")
public class JavaConfig {
}
然後,在專案啟動中載入配置類,在配置類中,通過 @ComponentScan 註解指定要掃描的包(如果不指定,預設情況下掃描的是配置類所在的包下載的 Bean 以及配置類所在的包下的子包下的類),然後就可以獲取 UserService 的例項了:
public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class); UserService userService = ctx.getBean(UserService.class); System.out.println(userService.getAllUser()); } }
這裡有幾個問題需要注意:
1.Bean 的名字叫什麼?
預設情況下,Bean 的名字是類名首字母小寫。例如上面的 UserService,它的例項名,預設就是 userService。如果開發者想要自定義名字,就直接在 @Service
註解中新增即可。
2.有幾種掃描方式?
上面的配置,我們是按照包的位置來掃描的。也就是說,Bean 必須放在指定的掃描位置,否則,即使你有 @Service 註解,也掃描不到。
除了按照包的位置來掃描,還有另外一種方式,就是根據註解來掃描。例如如下配置:
@Configuration
@ComponentScan(basePackages = "org.javaboy.javaconfig",useDefaultFilters = true,excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)})
public class JavaConfig {
}
這個配置表示掃描 org.javaboy.javaconfig 下的所有 Bean,但是除了 Controller。
XML配置自動化掃描
<context:component-scan base-package="org.javaboy.javaconfig"/>
上面這行配置表示掃描 org.javaboy.javaconfig 下的所有 Bean。當然也可以按照類來掃描。
XML 配置完成後,在 Java 程式碼中載入 XML 配置即可。
public class XMLTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = ctx.getBean(UserService.class);
List<String> list = userService.getAllUser();
System.out.println(list);
}
}
也可以在 XML 配置中按照註解的型別進行掃描:
<context:component-scan base-package="org.javaboy.javaconfig" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
自動掃描時的物件注入有三種方式:
- @Autowired
- @Resources
- @Injected
@Autowired 是根據型別去查詢,然後賦值,這就有一個要求,這個型別只可以有一個物件,否則就會報錯。
@Resources 是根據名稱去查詢,預設情況下,定義的變數名,就是查詢的名稱,當然開發者也可以在 @Resources註解中手動指定。所以,如果一個類存在多個例項,那麼就應該使用 @Resources 去注入,
如果使用@Autowired,也是可以的,此時需要配合另外一個註解,@Qualifier,在 @Qualifier 中可以指定變數名,兩個一起用(@Qualifier
和 @Autowired)就可以實現通過變數名查詢到變數。
@Service
public class UserService {
@Autowired
UserDao userDao;
public String hello() {
return userDao.hello();
}
public List<String> getAllUser() {
List<String> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
users.add("javaboy:" + i);
}
return users;
}
}