【Spring Framework】spring管理自己new的对象
使用AutowireCapableBeanFactory手动注入
使用.newInstance();创建对象的话,如果其他对象都使用Spring Autowired,还需要手动创建所有依赖的Bean:
private @Autowired AutowireCapableBeanFactory beanFactory;
public void process() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}
例如策略工厂中可以
private @Autowired AutowireCapableBeanFactory beanFactory;
/**
* 使用策略工厂获取具体策略实现
* @param code
* @return
*/
public PayStrategy getPayStrategy(String code) {
String className = PayEnumStrategy.getClassNameByCode(code);
try {
PayStrategy str = (PayStrategy) Class.forName(className).getDeclaredConstructor().newInstance();
beanFactory.autowireBean(str);
return str;
} catch (InstantiationException |
NoSuchMethodException |
ClassNotFoundException |
IllegalAccessException |
InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
但是这种方式只有对field注入方式才有用。
使用Map<String,?> 自动注入
先附上如下的代码:
public interface TalkService {
void talk(String content);
}
@Service(value = "withSisterTalkService")
public class WithSisterTalkService implements TalkService {
@Override
public void talk(String content) {
System.out.println(this.getClass().getName() + ":" + content);
}
}
@Service(value = "withGirlFriendTalkService")
public class WithGirlFriendTalkService implements TalkService {
@Override
public void talk(String content) {
System.out.println(this.getClass().getName() + ":" + content);
}
}
@Service
public class TalkServiceStrategyContext implements TalkService {
private Map<String, TalkService> strategyMap = new ConcurrentHashMap<>();
@Autowired
public TalkServiceStrategyContext(Map<String, TalkService> strategyMap) {
this.strategyMap.clear();
this.strategyMap.putAll(strategyMap);
}
@Override
public void talk(String content) {
}
}
注意,这里必须是Map<String, TalkService>类型!
@Autowired
private Map<String, TalkService> talkServiceMap;
@GetMapping(value = "doTest")
public String doTest() {
Set<String> strings = talkServiceMap.keySet();
for (String string : strings) {
System.out.println(string + ":" + talkServiceMap.get(string).toString());
}
return this.getClass().getName();
}
其访问测试controller后,打印的信息如下:
talkServiceStrategyContext:com.haiyang.onlinejava.complier.service.impl.TalkServiceStrategyContext@2f0b1419
withGirlFriendTalkService:com.haiyang.onlinejava.complier.service.impl.WithGirlFriendTalkService@1cf19a02
withSisterTalkService:com.haiyang.onlinejava.complier.service.impl.WithSisterTalkService@1ef3c76d
看了后感觉很奇怪,在上方只定义了一个map<String,TalkService>的map,居然它就能自动找到实现了TalkService的所有bean,并将service的beanName作为了key,感觉还是牛逼啊,spring的注解居然还能这样用。
然后简单看了下Autowired的源码,其javaDoc文档里也有说明:
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a constructor, field, setter method or config method as to be
* autowired by Spring's dependency injection facilities.
*
* <p>Only one constructor (at max) of any given bean class may carry this
* annotation, indicating the constructor to autowire when used as a Spring
* bean. Such a constructor does not have to be public.
*
* <p>Fields are injected right after construction of a bean, before any
* config methods are invoked. Such a config field does not have to be public.
*
* <p>Config methods may have an arbitrary name and any number of arguments;
* each of those arguments will be autowired with a matching bean in the
* Spring container. Bean property setter methods are effectively just
* a special case of such a general config method. Such config methods
* do not have to be public.
*
* <p>In the case of multiple argument methods, the 'required' parameter is
* applicable for all arguments.
*
* <p>In case of a {@link java.util.Collection} or {@link java.util.Map}
* dependency type, the container will autowire all beans matching the
* declared value type. In case of a Map, the keys must be declared as
* type String and will be resolved to the corresponding bean names.
*
* <p>Note that actual injection is performed through a
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} which in turn means that you <em>cannot</em>
* use {@code @Autowired} to inject references into
* {@link org.springframework.beans.factory.config.BeanPostProcessor
* BeanPostProcessor} or
* {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
* types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
* class (which, by default, checks for the presence of this annotation).
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
关注这句:
In case of a java.util.Collection or java.util.Map dependency type, the container will autowire all beans matching the declared value type. In case of a Map, the keys must be declared as type String and will be resolved to the corresponding bean names.
它大致是说Autowired当使用在Collection里时,会将所申明类的所有实现类都放在那个指定的Collection里;
如果Autowired和map使用的话呢,它将它bean的名称作为key,所有的bean作为value.
使用Set<?>自动注入
如果不想使用bean的名字作为map的Key的话,我们可以自定义寻址方式,自动注入时候使用Set<?>:
public interface Strategy {
void doStuff();
StrategyName getStrategyName();
}
public enum StrategyName {
StrategyA,
StrategyB,
StrategyC
}
@Component
public class StrategyA implements Strategy{
@Override
public void doStuff() {
//implement algorithm A here
}
@Override
public StrategyName getStrategyName() {
return StrategyName.StrategyA;
}
}
@Component
public class StrategyB implements Strategy{
@Override
public void doStuff() {
//implement algorithm B here
}
@Override
public StrategyName getStrategyName() {
return StrategyName.StrategyB;
}
}
@Component
public class StrategyC implements Strategy{
@Override
public void doStuff() {
}
@Override
public StrategyName getStrategyName() {
return StrategyName.StrategyC;
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Component;
@Component
public class StrategyFactory {
private Map<StrategyName, Strategy> strategies;
@Autowired
public StrategyFactory(Set<Strategy> strategySet) {
createStrategy(strategySet);
}
public Strategy findStrategy(StrategyName strategyName) {
return strategies.get(strategyName);
}
private void createStrategy(Set<Strategy> strategySet) {
strategies = new HashMap<StrategyName, Strategy>();
strategySet.forEach(
strategy ->strategies.put(strategy.getStrategyName(), strategy));
}
}
Now we can inject StrategyFactory using @Autowired annotation. Here is the sample code using our StrategyFactory.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SomeService {
@Autowired
private StrategyFactory strategyFactory;
public void findSome(){
// Now get the strategy by passing the name
Strategy strategy = strategyFactory.findStrategy(StrategyName.StrategyA);
// you can now call the methods defined in strategy.
strategy.doStuff();
}
}
【Spring Framework】spring管理自己new的对象的更多相关文章
- Difference between BeanFactory and FactoryBean in Spring Framework (Spring BeanFactory与Factory区别)
参见原文:http://www.geekabyte.io/2014/11/difference-between-beanfactory-and.html geekAbyte Codes and Ran ...
- 1.Spring Framework 5.0 入门篇
1.为什么学习Spring? 随着对Java EE的不断接触和理解,你会发现Spring 在各个企业和项目中发挥着越来越重要的作用.掌握Spring 已成为我们IT行业生存必学的本领之一. Spri ...
- Spring Framework(框架)整体架构 变迁
Spring Framework(框架)整体架构 2018年04月24日 11:16:41 阅读数:1444 标签: Spring框架架构 更多 个人分类: Spring框架 版权声明:本文为博主 ...
- Spring Framework 官方文档学习(二)之IoC容器与bean lifecycle
到目前为止,已经看了一百页.再次感慨下,如果想使用Spring,那可以看视频或者找例子,但如果想深入理解Spring,最好还是看官方文档. 原计划是把一些基本接口的功能.层次以及彼此的关系罗列一下.同 ...
- Benefits of Using the Spring Framework Dependency Injection 依赖注入 控制反转
小结: 1. Dependency Injection is merely one concrete example of Inversion of Control. 依赖注入是仅仅是控制反转的一个具 ...
- 框架应用:Spring framework (四) - 事务管理
事务控制 事务是什么?事务控制? 事务这个词最早是在数据库中进行应用,讲的用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位. 事务的管理是指一个事务的开启,内容添加, ...
- Spring Framework核心概念之Bean生命周期管理
目录 Spring Bean的生命周期 相关接口的分类 测试SpringBean生命周期的Demo程序 小结 Spring Bean的生命周期 Spring容器既Application或者WebApp ...
- 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文
在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...
- 【Spring Framework】Spring入门教程(八)Spring的事务管理
事务是什么? 事务:指单个逻辑操作单元的集合. 在操作数据库时(增删改),如果同时操作多次数据,我们从业务希望,要么全部成功,要么全部失败.这种情况称为事务处理. 例如:A转账给B. 第一步,扣除A君 ...
- 第四章 Spring.Net 如何管理您的类___让对象了解自己的容器
我们在开发中,经常需要让对象了解自己所在的容器的信息,例如,有时我们需要让对象知道,对象所在容器的引用是什么,或者是对象在容器中的名称是什么 .Spring.Net 中提供了两个接口,我们使用这两个接 ...
随机推荐
- 如何系统学习C 语言(下)之 预处理命令篇
大话c语言(下)之 预处理命令篇 预处理就是在编译之前,通过一些预处理命令对源代码进行管理和控制的过程. 由源代码得到可执行的程序,会经过预处理.编译.汇编和链接几个过程 预处理命令大致可以分为文件包 ...
- C#简单配置类及数据绑定
目录 简介 配置基类 派生配置类 数据绑定 Winform中的数据绑定 WPF下的数据绑定 附件 简介 本文实现一个简单的配置类,原理比较简单,适用于一些小型项目.主要实现以下功能: 保存配置到jso ...
- IIS设置URL重写,实现页面的跳转的重定向方法
默认IIS是不提供URL重写模块的. 请注意,不要将IIS默认的HTTP重定向理解为url重写. 安装url重写模块 url重写,是要从iis的应用市场下载url重写组件才可以的. URL重写工具的下 ...
- 设计模式学习-使用go实现享元模式
享元模式 定义 优点 缺点 适用场景 代码实现 享元模式和单例模式的区别 参考 享元模式 定义 享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象. 享元模式的意图是复用对象,节省 ...
- 微信小程序(五)
JavaScript: JavaScript 是一种轻量的,解释型的,面对对象的头等函数语言,是一种动态的基于原型和多范式的脚本语言,支持面向对象,命令式和函数式的编程风格. Nodejs 中的Jav ...
- [cf461D]Appleman and Complicated Task
假设该矩形是aij,那么有a(i,j)=a(i-1,j-1)^a(i-1,j+1)^a(i-2,j),不断递归下去可以发现a(i,j)=a(1,y-x+1)^a(1,y-x+3)^--^a(1,x+y ...
- [bzoj2257]瓶子和燃料
先考虑选出k个后答案最小会是多少,容易发现其实就是所有的gcd(就是$ax+by=gcd(a,b)$的推广)然后相当于要最大化gcd,反过来可以将所有数的约数都打上+1标记,+1标记不少于k个且最大的 ...
- page_fault_in_nonpaged_area异常解决方案(已解决)
电脑在运行虚拟机的时候异常重启,多次打开结果一样,问了客服告诉我导致蓝屏的原因很多,可能是驱动不兼容,系统,或其他.{没点有用的} 百度到这个方案: 打开->此电脑->右键属性->高 ...
- Golang - 关于 proto 文件的一点小思考
目录 前言 helloworld.proto 小思考 小结 推荐阅读 前言 ProtoBuf 是什么? ProtoBuf 是一套接口描述语言(IDL),通俗的讲是一种数据表达方式,也可以称为数据交换格 ...
- SpringCloud微服务实战——搭建企业级开发框架(二十五):实现多租户多平台短信通知服务
目前系统集成短信似乎是必不可少的部分,由于各种云平台都提供了不同的短信通道,这里我们增加多租户多通道的短信验证码,并增加配置项,使系统可以支持多家云平台提供的短信服务.这里以阿里云和腾讯云为例,集成短 ...