1. 程式人生 > 實用技巧 >自動化配置

自動化配置

例如我有一個 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>

自動掃描時的物件注入有三種方式:

  1. @Autowired
  2. @Resources
  3. @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;
    }
}