我正在编写一个实现以下方法的类:
public void run(javax.sql.DataSource dataSource);
在此方法中,我希望使用类似于以下的配置文件构造Spring应用程序上下文:
是否可以强制Spring在配置文件中引用"dataSource"bean的任何地方使用传递给我的方法的DataSource对象?
我一直处于相同的情况.由于没有人提出我的解决方案(我认为我的解决方案更优雅),我会在这里为后代添加它:-)
该解决方案包括两个步骤:
创建父ApplicationContext并在其中注册现有的bean.
创建子ApplicationContext(在父上下文中传递)并从XML文件加载bean
步骤1:
//create parent BeanFactory DefaultListableBeanFactory parentBeanFactory = new DefaultListableBeanFactory(); //register your pre-fabricated object in it parentBeanFactory.registerSingleton("dataSource", dataSource); //wrap BeanFactory inside ApplicationContext GenericApplicationContext parentContext = new GenericApplicationContext(parentBeanFactory); parentContext.refresh(); //as suggested "itzgeoff", to overcome a warning about events
第2步:
//create your "child" ApplicationContext that contains the beans from "beans.xml" //note that we are passing previously made parent ApplicationContext as parent ApplicationContext context = new ClassPathXmlApplicationContext( new String[] {"beans.xml"}, parentContext);
我发现可以使用两个Spring接口来实现我需要的东西.该BeanNameAware接口允许Spring通过调用来告诉一个对象的应用程序上下文中它的名字setBeanName(字符串)方法.该FactoryBean的接口告诉Spring不使用对象本身,而是当对象返回的getObject()方法被调用.把它们放在一起你会得到:
public class PlaceholderBean implements BeanNameAware, FactoryBean { public static MapbeansByName = new HashMap (); private String beanName; @Override public void setBeanName(String beanName) { this.beanName = beanName; } @Override public Object getObject() { return beansByName.get(beanName); } @Override public Class> getObjectType() { return beansByName.get(beanName).getClass(); } @Override public boolean isSingleton() { return true; } }
bean定义现在简化为:
占位符在创建应用程序上下文之前接收其值.
public void run(DataSource externalDataSource) { PlaceholderBean.beansByName.put("dataSource", externalDataSource); ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); assert externalDataSource == context.getBean("dataSource"); }
事情似乎成功了!