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的话,以后注入的话也可以使用泛型限定式依赖注入 :
- @Autowired
- private Repository<User> userRepository;
对于泛型依赖注入,最好使用setter注入,这样万一子类想变,比较容易切换。比如https://github.com/zhangkaitao/es,如果有多个实现时,子类可以使用@Qualifier指定使用哪一个。