使用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的对象的更多相关文章

  1. 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 ...

  2. 1.Spring Framework 5.0 入门篇

    1.为什么学习Spring? 随着对Java EE的不断接触和理解,你会发现Spring  在各个企业和项目中发挥着越来越重要的作用.掌握Spring 已成为我们IT行业生存必学的本领之一. Spri ...

  3. Spring Framework(框架)整体架构 变迁

    Spring Framework(框架)整体架构 2018年04月24日 11:16:41 阅读数:1444 标签: Spring框架架构 更多 个人分类: Spring框架   版权声明:本文为博主 ...

  4. Spring Framework 官方文档学习(二)之IoC容器与bean lifecycle

    到目前为止,已经看了一百页.再次感慨下,如果想使用Spring,那可以看视频或者找例子,但如果想深入理解Spring,最好还是看官方文档. 原计划是把一些基本接口的功能.层次以及彼此的关系罗列一下.同 ...

  5. Benefits of Using the Spring Framework Dependency Injection 依赖注入 控制反转

    小结: 1. Dependency Injection is merely one concrete example of Inversion of Control. 依赖注入是仅仅是控制反转的一个具 ...

  6. 框架应用:Spring framework (四) - 事务管理

    事务控制 事务是什么?事务控制? 事务这个词最早是在数据库中进行应用,讲的用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位. 事务的管理是指一个事务的开启,内容添加, ...

  7. Spring Framework核心概念之Bean生命周期管理

    目录 Spring Bean的生命周期 相关接口的分类 测试SpringBean生命周期的Demo程序 小结 Spring Bean的生命周期 Spring容器既Application或者WebApp ...

  8. 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文

    在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...

  9. 【Spring Framework】Spring入门教程(八)Spring的事务管理

    事务是什么? 事务:指单个逻辑操作单元的集合. 在操作数据库时(增删改),如果同时操作多次数据,我们从业务希望,要么全部成功,要么全部失败.这种情况称为事务处理. 例如:A转账给B. 第一步,扣除A君 ...

  10. 第四章 Spring.Net 如何管理您的类___让对象了解自己的容器

    我们在开发中,经常需要让对象了解自己所在的容器的信息,例如,有时我们需要让对象知道,对象所在容器的引用是什么,或者是对象在容器中的名称是什么 .Spring.Net 中提供了两个接口,我们使用这两个接 ...

随机推荐

  1. flower 指定app

    flower 指定app # tasks.py from celery import Celery celery = Celery(broker="amqp://", backen ...

  2. 【不费脑筋系列】发布个人的代码包到Nuget服务器上,并通过VS引用进行使用的方法

      打打酱油,写点不需要费脑筋的博客先压压惊. 下面讲个关于个人如何开发nuget包,并部署到nuget服务器上的例子.为了保证.net framework和 .net core都可以访问到我的包,我 ...

  3. Part 27 Remove # from URL AngularJS

    There are 4 simple steps to remove # from URLs in Angular. Step 1 : Enable html5mode routing. To do ...

  4. 如何用命令行编译c++程序

    作为程序员,如果仅仅只懂得如何在IDE上拖控件写程序,而不知道如何直接通过编译器编译程序的话.虽然说也没啥大不了的,但是如果掌握了手动编译的技能,那肯定会是一种炫技般的存在.从客观的角度来讲,一方面, ...

  5. vue如何写组件(script标签引入的方式)

    很多人知道.vue结构的单文件组件形式,不过这种单文件组件的结构如果要加入到现有的jquery项目中就比较麻烦了,那如果我们又想用vue来写模板,又不想引入vue-cli管理,那该怎么来写组件呢?别着 ...

  6. IDEA maven Run Maven 启动方式

    首先想要使用 Run Maven 启动需要在IDEA设置里找到plugins  在plugins窗口下面找到Browse Repositories   打开Browse Repositories 下载 ...

  7. myeclipse自带tomcat

    安装myeclipse自带的tomcat没有在myeclipse的安装目录下,是再myeclipse指定的工作空间下 的.metadata\.plugins\com.genuitec.eclipse. ...

  8. [atARC086F]Shift and Decrement

    将$A$操作看作直接除以2(保留小数),最终再将$a_{i}$取整 记$k$表示$A$操作的次数,$p_{i}$表示第$i$次$A$和第$i+1$次$A$之间$B$操作的次数(特别的,$p_{0}$为 ...

  9. form-create 3.0 版本发布,好用的Vue3版本动态表单生成组件

    form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成组件.支持2个UI框架,并且支持生成任何 Vue 组件.内置20种常用表单组件和自定义组件,再复杂 ...

  10. Codeforces 1067E - Random Forest Rank(找性质+树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...