Spring4新特性:泛型限定式依賴注入
Spring 4.0已經發布RELEASE版本,不僅支援Java8,而且向下相容到JavaSE6/JavaEE6,並移出了相關廢棄類,新新增如Java8的支援、Groovy式Bean定義DSL、對核心容器進行增強、對Web框架的增強、Websocket模組的實現、測試的增強等。其中兩個我一直想要的增強就是:支援泛型依賴注入、對cglib類代理不再要求必須有空參構造器了。具體更新請參考:
1、相關程式碼:
1.1、Entity
- publicclass User implements Serializable {
- private Long id;
-
private String name;
- }
- publicclass Organization implements Serializable {
- private Long id;
- private String name;
- }
- publicabstractclass BaseRepository<M extends Serializable> {
- publicvoid save(M m) {
- System.out.println("=====repository save:" + m);
- }
- }
-
@Repository
- publicclass UserRepository extends BaseRepository<User> {
- }
- @Repository
- publicclass OrganizationRepository extends BaseRepository<Organization> {
- }
1.3、Service
1.3.1、以前Service寫法
-
publicabstract
- private BaseRepository<M> repository;
- publicvoid setRepository(BaseRepository<M> repository) {
- this.repository = repository;
- }
- publicvoid save(M m) {
- repository.save(m);
- }
- }
- @Service
- publicclass UserService extends BaseService<User> {
- @Autowired
- publicvoid setUserRepository(UserRepository userRepository) {
- setRepository(userRepository);
- }
- }
- @Service
- publicclass OrganizationService extends BaseService<Organization> {
- @Autowired
- publicvoid setOrganizationRepository(OrganizationRepository organizationRepository) {
- setRepository(organizationRepository);
- }
- }
1.3.2、泛型Service的寫法
- publicabstractclass BaseService<M extends Serializable> {
- @Autowired
- protected BaseRepository<M> repository;
- publicvoid save(M m) {
- repository.save(m);
- }
- }
- @Service
- publicclass UserService extends BaseService<User> {
- }
- @Service
- publicclass OrganizationService extends BaseService<Organization> {
- }
大家可以看到,現在的寫法非常簡潔。支援泛型式依賴注入。
這個也是我之前非常想要的一個功能,這樣對於那些基本的CRUD式程式碼,可以簡化更多的程式碼。
如果大家用過Spring data jpa的話,以後注入的話也可以使用泛型限定式依賴注入 :
- @Autowired
- private Repository<User> userRepository;
1.4 Map依賴注入:
- @Autowired
- private Map<String, BaseService> map;
這樣會注入:key是bean名字;value就是所有實現了BaseService的Bean,假設使用上一篇的例子,則會得到:
{orga[email protected]617029,[email protected]}
1.5 List/陣列注入:
- @Autowired
- private List<BaseService> list;
- @Order(value = 1)
- @Service
- publicclass UserService extends BaseService<User> {
- }
1.6 @Lazy可以延遲依賴注入:
- @Lazy
- @Service
- publicclass UserService extends BaseService<User> {
- }
- @Lazy
- @Autowired
- private UserService userService;
1.7 @Conditional
@Conditional類似於@Profile(一般用於如我們有開發環境、測試環境、正式機環境,為了方便切換不同的環境可以使用
@Profile指定各個環境的配置,然後通過某個配置來開啟某一個環境,方便切換)
,但是@Conditional的優點是允許自己定義規則。可以指定在如@Component、@Bean、@Configuration等註解的類上,以絕對Bean是否建立等。首先來看看使用@Profile的用例,假設我們有個使用者模組:
1、在測試/開發期間呼叫本機的模擬介面方便開發;
2、在部署到正式機時換成呼叫遠端介面;
- publicabstractclass UserService extends BaseService<User> {
- }
- @Profile("local")
- @Service
- publicclass LocalUserService extends UserService {
- }
- @Profile("remote")
- @Service
- publicclass RemoteUserService extends UserService {
- }
- @ActiveProfiles("remote")
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = "classpath:spring-config.xml")
- publicclass ServiceTest {
- @Autowired
- private UserService userService;
- }
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Conditional(CustomCondition.class)
- public@interface Local {
- }
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Conditional(CustomCondition.class)
- public@interface Remote {
- }
- publicclass CustomCondition implements Condition {
- @Override
- publicboolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- boolean isLocalBean = metadata.isAnnotated("com.sishuok.spring4.annotation.Local");
- boolean isRemoteBean = metadata.isAnnotated("com.sishuok.spring4.annotation.Remote");
- //如果bean沒有註解@Local或@Remote,返回true,表示建立Bean
- if(!isLocalBean && !isRemoteBean) {
- returntrue;
- }
- boolean isLocalProfile = context.getEnvironment().acceptsProfiles("local");
- //如果profile=local 且 bean註解了@Local,則返回true 表示建立bean;
- if(isLocalProfile) {
- return isLocalBean;
- }
- //否則預設返回註解了@Remote或沒有註解@Remote的Bean
- return isRemoteBean;
- }
- }