Spring动态创建bean

最近有个项目场景,多垂类支持,大体业务流程相同,只是一些业务规则的校验参数不同。解决思路是将业务参数作为类的属性,然后创建垂类数量个实例,去处理不同垂类的业务。

看了spring ioc部分的代码,个人感觉在spring完成bean创建的过程后,做一个类实现ApplicationContextAware接口,然后克隆多个需要的BeanDefinition,附不同的业务参数属性值的方式比较讨巧。新增加的BeanDefinition会在getBean的过程中,由spring创建。

下面分两部分介绍:
1、动态创建bean的代码实现
2、spring的ioc源码解读,这部分放到另外一篇博客[url]http://mazhen2010.iteye.com/blog/2283773[/url]
<spring.version>4.0.6.RELEASE</spring.version>

【动态创建bean的代码实现】
1、创建一个实现ApplicationContextAware接口的类,然后获取DefaultListableBeanFactory

private void setSpringFactory(ApplicationContext applicationContext) {

if (applicationContext instanceof AbstractRefreshableApplicationContext) {
// suit both XmlWebApplicationContext and ClassPathXmlApplicationContext
AbstractRefreshableApplicationContext springContext = (AbstractRefreshableApplicationContext) applicationContext;
if (!(springContext.getBeanFactory() instanceof DefaultListableBeanFactory)) {
LOGGER.error("No suitable bean factory! The current factory class is {}",
springContext.getBeanFactory().getClass());
}
springFactory = (DefaultListableBeanFactory) springContext.getBeanFactory();
} else if (applicationContext instanceof GenericApplicationContext) {
// suit GenericApplicationContext
GenericApplicationContext springContext = (GenericApplicationContext) applicationContext;
springFactory = springContext.getDefaultListableBeanFactory();
} else {
LOGGER.error("No suitable application context! The current context class is {}",
applicationContext.getClass());
}
}


2、定义注解,以找到需要克隆的BeaDefinition和需要赋值的属性

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TemplateService {

//服务名称
String serviceName();
//服务实现名称
String value() default "";
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TemplateBizParam {
}

@TemplateService(serviceName = "demoService", value = "demoServiceImpl")
public class DemoServiceImpl extends AbstractServiceImpl implements DemoService {

@TemplateBizParam
private String noVisitDays;

@Override
public void doDemo(Long poiId) {
StringBuilder builder = new StringBuilder("doDemo").append("//").append("poiId:").append(poiId);
builder.append("//").append(noVisitDays).append("//").append(getExtendFields()).append("//");
builder.append("abc:").append(getExtendField("abc"));
System.out.println(builder.toString());
}

@Override
public void doDemos(List<Long> poiIds) {
System.out.println("poiIds" + poiIds + "; noVisitDays:" + noVisitDays);
}

}


3、从垂类模板中获取需要动态创建的bean信息,然后注册BeanDefinition

private void registerBeanDefinition(String templateId, ServiceEntity serviceEntity) {

try {
if (springFactory.containsBeanDefinition(serviceEntity.getImplName())) {
//step1: 注入多个实例
String beanKey = generateTemplateBeanName(templateId, serviceEntity.getServiceName());
BeanDefinition beanDefinition = springFactory.getBeanDefinition(serviceEntity.getImplName());
String className = beanDefinition.getBeanClassName();
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(className);
beanDefinitionBuilder.getBeanDefinition().setAttribute("id", beanKey);

springFactory.registerBeanDefinition(
beanKey, beanDefinitionBuilder.getBeanDefinition());
LOGGER.info("Register bean definition successfully. beanName:{}, implName:{}",
generateTemplateBeanName(templateId, serviceEntity.getServiceName()), serviceEntity.getImplName());

//step2: 为实例自动化注入属性
Object bean = springFactory.getBean(beanKey, c);
injectParamVaules(bean, c, serviceEntity);
}

} catch (NoSuchBeanDefinitionException ex) {
LOGGER.info("No bean definition
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值