`
jinnianshilongnian
  • 浏览: 21437095 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2405558
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:2998127
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5631794
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:257649
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1593328
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:249020
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5847952
Group-logo
跟我学Nginx+Lua开...
浏览量:698265
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:780624
社区版块
存档分类
最新评论

Spring4新特性——泛型限定式依赖注入

阅读更多

Spring4新特性——泛型限定式依赖注入

Spring4新特性——核心容器的其他改进

Spring4新特性——Web开发的增强

Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 

Spring4新特性——Groovy Bean定义DSL

Spring4新特性——更好的Java泛型操作API 

Spring4新特性——JSR310日期API的支持

Spring4新特性——注解、脚本、任务、MVC等其他特性改进 

 

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

 

1、相关代码:

1.1、实体

public class User implements Serializable {
    private Long id;
    private String name;
}

public class Organization implements Serializable {
    private Long id;
    private String name;
}

 1.2、Repository

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

@Repository
public class UserRepository extends BaseRepository<User> {
}

@Repository
public class OrganizationRepository extends BaseRepository<Organization> {
}

 对于Repository,我们一般是这样实现的:首先写一个模板父类,把通用的crud等代码放在BaseRepository;然后子类继承后,只需要添加额外的实现。

 

1.3、Service

1.3.1、以前Service写法

public abstract class BaseService<M extends Serializable> {
    private BaseRepository<M> repository;
    public void setRepository(BaseRepository<M> repository) {
        this.repository = repository;
    }
    public void save(M m) {
        repository.save(m);
    }
}
@Service
public class UserService extends BaseService<User> {
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        setRepository(userRepository);
    }
}

@Service
public class OrganizationService extends BaseService<Organization> {
    @Autowired
    public void setOrganizationRepository(OrganizationRepository organizationRepository) {
        setRepository(organizationRepository);
    }
}

 

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

 

1.3.2、泛型Service的写法

public abstract class BaseService<M extends Serializable> {
    @Autowired
    protected BaseRepository<M> repository;

    public void save(M m) {
        repository.save(m);
    }
}

@Service
public class UserService extends BaseService<User> {
}

@Service
public class OrganizationService extends BaseService<Organization> {
}

 

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

 

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

 

 

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

@Autowired
private Repository<User> userRepository;

 

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

 

21
3
分享到:
评论
21 楼 manong_java 2013-12-19  
我貌似找到原因了有两个同类型的Dao:UserDao和UserDao1
且所有Service 继承BaseService<T> ,去掉BaseService的继承则可以正常运行。
这样一来就说明BaseService中的BaseDao<T>不会根据具体的service类型来注入。

public abstract class BaseService<T extends Serializable> {

	@Autowired
	private BaseDao<T> baseDao;
	
	public void save(T t)
	{
		baseDao.save(t);
	}
}

@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}
}


	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userservice=ctx.getBean(UserService.class);
		User user=new User();
		user.setName("张三");
		user.setId(1000);
		userservice.save(user);
	}


jinnianshilongnian 写道
manong_java 写道
jinnianshilongnian 写道
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????
可以的啊 比如 Repository<User> 即可注入


我定义了两个Dao:UserDao、UserDao1
我在service实现类中指定使用UserDao1 但没起作用,程序启动抛异常 这是什么原因呢?

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.hulibo.spring.dao.impl.BaseDao] is defined: expected single matching bean but found 2: UserDao,UserDao1


@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}

}


@Repository("UserDao")
public class UserDao extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao save :"+t.getName());
	}

	
}



@Repository("UserDao1")
public class UserDao1 extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao1 save>>>>:"+t.getName());
	}
}




很明显   BaseDao<User>  有两个实现,不过你指定了@Qualifier("UserDao1") 不应该有问题的啊
20 楼 jinnianshilongnian 2013-12-19  
manong_java 写道
是的我故意写两个Repository<user>来测试根据类型自动注入,但事实就是出现这个异常
tao哥帮忙解决下呗
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userservice=ctx.getBean(UserService.class);
		User user=new User();
		user.setName("张三");
		user.setId(1000);
		userservice.save(user);
	}


jinnianshilongnian 写道
manong_java 写道
jinnianshilongnian 写道
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????

可以的啊 比如 Repository<User> 即可注入


我定义了两个Dao:UserDao、UserDao1
我在service实现类中指定使用UserDao1 但没起作用,程序启动抛异常 这是什么原因呢?

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.hulibo.spring.dao.impl.BaseDao] is defined: expected single matching bean but found 2: UserDao,UserDao1


@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}

}


@Repository("UserDao")
public class UserDao extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao save :"+t.getName());
	}

	
}



@Repository("UserDao1")
public class UserDao1 extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao1 save>>>>:"+t.getName());
	}
}




很明显   BaseDao<User>  有两个实现,不过你指定了@Qualifier("UserDao1") 不应该有问题的啊

你把代码站内信我 我看看
19 楼 manong_java 2013-12-19  
是的我故意写两个Repository<user>来测试根据类型自动注入,但事实就是出现这个异常
tao哥帮忙解决下呗
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userservice=ctx.getBean(UserService.class);
		User user=new User();
		user.setName("张三");
		user.setId(1000);
		userservice.save(user);
	}


jinnianshilongnian 写道
manong_java 写道
jinnianshilongnian 写道
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????

可以的啊 比如 Repository<User> 即可注入


我定义了两个Dao:UserDao、UserDao1
我在service实现类中指定使用UserDao1 但没起作用,程序启动抛异常 这是什么原因呢?

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.hulibo.spring.dao.impl.BaseDao] is defined: expected single matching bean but found 2: UserDao,UserDao1


@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}

}


@Repository("UserDao")
public class UserDao extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao save :"+t.getName());
	}

	
}



@Repository("UserDao1")
public class UserDao1 extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao1 save>>>>:"+t.getName());
	}
}




很明显   BaseDao<User>  有两个实现,不过你指定了@Qualifier("UserDao1") 不应该有问题的啊
18 楼 jinnianshilongnian 2013-12-19  
manong_java 写道
jinnianshilongnian 写道
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????

可以的啊 比如 Repository<User> 即可注入


我定义了两个Dao:UserDao、UserDao1
我在service实现类中指定使用UserDao1 但没起作用,程序启动抛异常 这是什么原因呢?

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.hulibo.spring.dao.impl.BaseDao] is defined: expected single matching bean but found 2: UserDao,UserDao1


@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}

}


@Repository("UserDao")
public class UserDao extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao save :"+t.getName());
	}

	
}



@Repository("UserDao1")
public class UserDao1 extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao1 save>>>>:"+t.getName());
	}
}




很明显   BaseDao<User>  有两个实现,不过你指定了@Qualifier("UserDao1") 不应该有问题的啊
17 楼 manong_java 2013-12-19  
jinnianshilongnian 写道
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????

可以的啊 比如 Repository<User> 即可注入


我定义了两个Dao:UserDao、UserDao1
我在service实现类中指定使用UserDao1 但没起作用,程序启动抛异常 这是什么原因呢?

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.hulibo.spring.dao.impl.BaseDao] is defined: expected single matching bean but found 2: UserDao,UserDao1


@Service
public class UserService extends BaseService<User> {

	@Autowired
	@Qualifier("UserDao1")
	private BaseDao<User> dao;
	
	@Override
	public void save(User t) {
		System.out.println("重写save user方法:"+t.getName());
		dao.save(t);
	}

}


@Repository("UserDao")
public class UserDao extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao save :"+t.getName());
	}

	
}



@Repository("UserDao1")
public class UserDao1 extends BaseDao<User> {

	@Override
	public void save(User t) {
		System.out.println("userDao1 save>>>>:"+t.getName());
	}
}


16 楼 jinnianshilongnian 2013-12-19  
manong_java 写道
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????

可以的啊 比如 Repository<User> 即可注入
15 楼 manong_java 2013-12-19  
他这个泛型支持 能根据user对象 自动注入UserRepository 对象吗?????
14 楼 keeley 2013-12-14  
厉害!......
13 楼 jinnianshilongnian 2013-12-14  
yandou524 写道

12 楼 yandou524 2013-12-14  
11 楼 jinnianshilongnian 2013-12-14  
fighting_2013 写道
这个改进真不错,方便了不少

是的,少写了好多setter代码;
10 楼 fighting_2013 2013-12-14  
这个改进真不错,方便了不少
9 楼 jinnianshilongnian 2013-12-14  
lucky16 写道
速度快。呵呵

  周末看看把spring4+hibernate validator5研究下 看看对分组那块支持是不是更方便了
8 楼 lucky16 2013-12-14  
速度快。呵呵
7 楼 jinnianshilongnian 2013-12-14  
maoweiwer 写道
开涛,请问org.springframework.test.jpa.AbstractJpaTests这个类在SPRING4中给移除了吗。我以前的项目包中使用到了这个类。现在想升级到4 发现找不到这个类了

从3开始推荐使用listener方式的上下文框架了;就不用再继承这一堆基类了;如:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config.xml")
public class ServiceTest {
6 楼 jinnianshilongnian 2013-12-14  
maoweiwer 写道
开涛,请问org.springframework.test.jpa.AbstractJpaTests这个类在SPRING4中给移除了吗。我以前的项目包中使用到了这个类。现在想升级到4 发现找不到这个类了

3.0时就Deprecated了,木有了;大部分Deprecated类都移出了;
5 楼 maoweiwer 2013-12-14  
开涛,请问org.springframework.test.jpa.AbstractJpaTests这个类在SPRING4中给移除了吗。我以前的项目包中使用到了这个类。现在想升级到4 发现找不到这个类了
4 楼 jinnianshilongnian 2013-12-14  
mqiy 写道
哥们速度没得说!!!

昨天晚上闲着没事 就写一写吧 反正举手之劳 
3 楼 jinnianshilongnian 2013-12-14  
jilen 写道
guice似乎一直都支持

是的,这个特性在做如泛型层的时候挺好用的,这样就不需要在每个子类再写注入代码了。
2 楼 jilen 2013-12-14  
guice似乎一直都支持

相关推荐

Global site tag (gtag.js) - Google Analytics