引言
IoC可以说是spring最核心的部分,是spring家族任意组件的基本。我们可以将Java Bean托管给Spring,Spring通过其IOC功能可以依次解析出Java Bean依赖的其他实例。能够使我们从复杂繁琐的对象依赖中解脱出来,专注于业务本身。
但是有时候我们需要动态地创建一些Java Bean,并且希望将这些对象托管给Spring或者使用Spring的IOC功能对对象依赖的各个Bean进行解析。本文将介绍以下两种使用场景
- 将Java Bean直接托管给Spring,使用的时候从Spring的Context里获取
- 仅仅使用Spring的IOC功能对对象的依赖进行解析,自己维护对象
将Java Bean托管给Spring
我们考虑这样一个场景,一个系统要通过SPI(Service Provider Interface)的方式调用不同的业务方,每个业务方需要向这个系统进行注册。如下图所示:
下游系统动态地向上游系统注册回到函数,当某个事件产生的时候上游系统通过SPI的模式进行回调下游业务方。因此我们需要在服务启动或者下游方注册的时候动态生成对应的回调Bean,方便在使用的时候直接可以通过Bean回调。
public class CallBackSpiService implements InitializingBean, ApplicationContextAware {
private static final String BEAN_PROFIX = "CallBackBean_";
private AbstractApplicationContext applicationContext;
@Override
public void afterPropertiesSet() throws Exception {
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = (AbstractApplicationContext) applicationContext;
}
private void init(){
//todo 查询出来所有的满足条件的注册数据
List<CallBackApply> applyList = callBackApplyMapper.selectByExample(ex);
if (CollectionUtils.isEmpty(applyList)){
return;
}
for (CallBackApply apply : applyList){
this.register(apply);
}
}
/**
* 注册bean
* @param apply
*/
private void register(CallBackApply apply){
String beanName = BEAN_PROFIX + apply.getId();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
//BeanDefinitionBuilder构造过程
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(ThriftClientProxy.class);
beanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
}
/**
* 获取SPI的bean
* @param applyId
* @return
*/
private Object getSpiBean(Long applyId){
String beanName = BEAN_PROFIX + applyId;
Object object = applicationContext.getBean(beanName);
if (object == null){
CallBackApply callBackApply = callBackApplyMapper.selectByPrimoryKey(applyId);
this.register(callBackApply);
object = applicationContext.getBean(beanName);
}
return object;
}
private Object buildRpcBean(CallBackApply apply){
return new Object();
}
}
我们可以通过实现ApplicationContextAware接口来获取Spring的Context,然后通过DefaultListableBeanFactory工厂类将我们需要托管给Spring的Java Bean注册到Context中。
当我们需要使用的时候可以通过之前我们注册的名字直接从Context中获取即可。
仅仅使用Spring IOC功能。
有时候我们在项目中需要New出来一些对象,但对象中有堆其他Bean的依赖,而我们不希望手动对其他依赖的Bean进行设置处理,这个时候就可以使用AutowireCapableBeanFactory对Bean进行自动依赖解析。
public class Dog {
@Resource
private RewardService rewardService;
public void doSomething(){
System.out.println("握手");
}
public void getReward(){
rewardService.get();
}
}
如上代码,我们在运行过程中希望New出来一个Dog对象,然后使用该对象。但我们New出来的对象是无法关联@Resource注解的RewardService对象的。为了解决这个问题,我们可以使用AutowireCapableBeanFactory对New出来的Bean进行解析。
@Service
public class AnimalCreate{
@Resource
private AutowireCapableBeanFactory beanFactory;
public void test(){
Dog dog = new Dog();
beanFactory.autowireBean(dog);
dog.getReward();
}
}
总结
将对象交给Spring容器管理,你只需要在spring配置文件总配置相应的bean,但是在实际工作中我们有时候需要手动创建Bean或者将Bean手动托管给Spring进行处理。通过上述两种方法基本可以解决我们日常遇到的这种问题。