spring4.0之六:Generic Qualifier(泛型限定)

 Spring 4.0已经发布RELEASE版本,不仅支持Java8,而且向下兼容到JavaSE6/JavaEE6,并移出了相关废弃类,新添加如Java8的支持、Groovy式Bean定义DSL、对核心容器进行增强、对Web框架的增强、Websocket模块的实现、测试的增强等。其中两个我一直想要的增强就是:支持泛型依赖注入、对cglib类代理不再要求必须有空参构造器了。具体更新请参考:

http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#new-in-4.0

 

model类:

package com.dxz.demo.generic.model;

import java.io.Serializable;

public class Organization implements Serializable {
    private Long id;
    private String name;
}
package com.dxz.demo.generic.model;

import java.io.Serializable;

public class User implements Serializable {
    private Long id;
    private String name;
    
    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}

dao类:

package com.dxz.demo.generic.dao;

import java.io.Serializable;

public abstract class BaseDao<M extends Serializable> {
    public void save(M m) {
        System.out.println("BaseDao save:" + m);
    }
}

package com.dxz.demo.generic.dao;

import org.springframework.stereotype.Repository;

import com.dxz.demo.generic.model.Organization;

@Repository  
public class OrganizationDao extends BaseDao<Organization> {  
} 
package com.dxz.demo.generic.dao;

import org.springframework.stereotype.Repository;

import com.dxz.demo.generic.model.User;

@Repository
public class UserDao extends BaseDao<User> {
}

以前Service写法:

package com.dxz.demo.generic.service.old;

import java.io.Serializable;

import com.dxz.demo.generic.dao.BaseDao;

public abstract class BaseService<M extends Serializable> {
    private BaseDao<M> dao;

    public void setDao(BaseDao<M> repository) {
        this.dao = repository;
    }

    public void save(M m) {
        System.out.println("old-----");
        dao.save(m);
    }
}

package com.dxz.demo.generic.service.old;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dxz.demo.generic.dao.OrganizationDao;
import com.dxz.demo.generic.model.Organization;

@Service
public class OrganizationService extends BaseService<Organization> {
    @Autowired
    public void setOrganizationRepository(OrganizationDao organizationDao) {
        setDao(organizationDao);
    }
}
package com.dxz.demo.generic.service.old;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dxz.demo.generic.dao.UserDao;
import com.dxz.demo.generic.model.User;

@Service
public class UserService extends BaseService<User> {
    @Autowired
    public void setUserDao(UserDao userDao) {
        setDao(userDao);
    }
}

可以看到,以前必须再写一个setter方法,然后指定注入的具体类型,然后进行注入;

 

service泛型Service的写法

package com.dxz.demo.generic.service.newf;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;

import com.dxz.demo.generic.dao.BaseDao;


public abstract class BaseService<M extends Serializable> {
    @Autowired
    protected BaseDao<M> dao;

    public void save(M m) {
        System.out.println("newf ----");
        dao.save(m);
    }
}
package com.dxz.demo.generic.service.newf;

import org.springframework.stereotype.Service;

import com.dxz.demo.generic.model.Organization;

@Service  
public class GOrganizationService extends BaseService<Organization> {  
}  
package com.dxz.demo.generic.service.newf;

import org.springframework.stereotype.Service;

import com.dxz.demo.generic.model.User;

@Service("gUserService")
public class GUserService extends BaseService<User> {  
}  
  

spring对bean的装配类:

package com.dxz.demo.generic;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
//添加自动扫描注解,basePackages为待注册bean的包路径
@ComponentScan(basePackages = "com.dxz.demo.generic")
public class GenericDemoConfiguration {
    public GenericDemoConfiguration() {
        System.out.println("GenericDemoConfiguration容器启动初始化。。。");
    }
}
package com.dxz.demo.generic;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(GenericDemoConfiguration.class)
public class GenericDemoConfig {
}

测试类:

package com.dxz.demo.generic;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.dxz.demo.generic.model.User;

public class TestMain {

    public static void main(String[] args) {
        // @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
        ApplicationContext context = new AnnotationConfigApplicationContext(GenericDemoConfig.class);
        com.dxz.demo.generic.service.newf.BaseService service = (com.dxz.demo.generic.service.newf.BaseService)context.getBean("gUserService");
        service.save(new User(1L,"duan"));
        
        com.dxz.demo.generic.service.old.BaseService service2 = (com.dxz.demo.generic.service.old.BaseService)context.getBean("userService");
        service2.save(new User(1L,"duan"));
    }

}

大家可以看到,现在的写法非常简洁。支持泛型式依赖注入。

 结果:

 

这个也是我之前非常想要的一个功能,这样对于那些基本的CRUD式代码,可以简化更多的代码。

 

 

如果大家用过Spring data jpa的话,以后注入的话也可以使用泛型限定式依赖注入 :

Java代码  收藏代码
  1. @Autowired  
  2. private Repository<User> userRepository;  

 

 对于泛型依赖注入,最好使用setter注入,这样万一子类想变,比较容易切换。比如https://github.com/zhangkaitao/es,如果有多个实现时,子类可以使用@Qualifier指定使用哪一个。

posted on 2017-09-08 14:43  duanxz  阅读(975)  评论(0编辑  收藏  举报