我有以下组件
- 使用 Spring MVC(war 文件)公开的 Web 应用程序。
- 一个库(jar 文件),它知道无论谁使用该库,都使用 spring。
场景
我的库有一个类,需要将自身注册为 Web 应用程序上下文中的 bean,而不告诉库的用户更改其代码(xml、spring 上下文或类)。
所以,换句话说,我有一个类和一个 spring 上下文,我只想从我的类中注册这个 spring 上下文,而不更改其中的任何内容。 那么spring是否会在类路径中扫描实现某个接口(interface)的类,如果有的话是什么接口(interface)?
我尝试过的
使用 BeanFactoryPostProcessor,但这需要我访问应用程序上下文并尽可能调用 addBeanFactoryPostProcessor。
使用 ApplicationContextInitializer 但这迫使我更改 web.xml
还有很多其他的东西,比如不同的 Aware 接口(interface),但我还没有找到任何东西可以让我的类 self 注册到 Bean Factory 并在 spring 上下文中被拾取,我希望能够使用诸如计划注释之类的东西。我总是希望 spring 上下文中的其他人能够通过 Autowired 注释找到我的类。
示例
我拥有并在我的库中的类
package spring.outside
public class ClassA {
@Scheduled(fixedDelay=5000)
public void doSomething() {
}
}
我的库的用户拥有的类
package spring.inside
public class ClassB {
@Autowired
private ClassA classA;
}
有一个包含类似内容的 spring 文件,但我不拥有
<context:component-scan base-package="spring.inside"/>
<小时/>
<小时/>
如果这是不可能的我想探索我在 Spring 的类里面可以做的事情的可能性,以尽可能轻松地告诉 Spring 上下文来拾取它。
示例
package spring.outside
public class ClassA {
@Scheduled(fixedDelay=5000)
public void doSomething() {
}
}
我的库的用户拥有的类
package spring.inside
public class ClassB {
@Autowired
private ClassA classA;
}
另一个类,用于启动 ClassA 并将其放入 spring 应用程序上下文中,我只是显示我现在在其中测试的一些不同事物的代码,因为我不知道它应该是什么样子.
package spring.inside
public class ClassC implements BeanFactoryPostProcessor, ApplicationContextInitializer, BeanFactoryAware, ApplicationContextAware {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerSingleton("classA", new ClassA());
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.addBeanFactoryPostProcessor(this);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
((ConfigurableListableBeanFactory)beanFactory).registerSingleton("classA", new ClassA());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
((ConfigurableApplicationContext)applicationContext.getParentBeanFactory()).addBeanFactoryPostProcessor(this);
((ConfigurableListableBeanFactory)applicationContext.getParentBeanFactory()).registerSingleton("classA", new ClassA());
}
}
尝试过
- 使用 BeanFactoryPostProcessor 和 registerSingleton 添加它
- 使用 ApplicationContextInitializer 添加它,然后结合使用 addBeanFactoryPostProcessor 和 BeanFactoryPostProcessor
- 通过BeanUtils.instantiate添加
- 通过实现 ApplicationContextAware 并将其转换为 ConfigurableApplicationContext 并添加 BeanFactoryPostPrecessor 实现来添加它,我还尝试了类型转换为 ConfigurableListableBeanFactory 和 registerSingleton。
- 使用 BeanFactoryAware 和 registerSingleton 来添加它。
- 将我的 ClassC 设置为一个配置,其中我为 spring.outside 包添加了 componentScan,效果非常好,但这样做感觉非常错误。
但是所有这些似乎都部分起作用,但最终总是会出现一些计时错误,例如:ClassA 需要在 ClassC 内部 Autowiring 的构造函数中输入变量,其中一些变量是在 ClassC 创建 ClassA 时设置的。我看到的另一个场景是 ClassB 无法自动连接 ClassA,因为之前已经完成了。那么正确且好的方法是什么?
我正在运行spring版本3.2.11.RELEASE
如果有人知道如何以一种好的方式解决这个问题,而不是感觉像“丑陋的黑客”的东西,我会很高兴知道!
谢谢并致以最诚挚的问候!
最佳答案
在这种情况下,您必须将 ClassA
作为 spring bean 包含在 Spring Context XML
<bean id="classA" class="spring.inside.ClassA">
或使用配置类
package spring.inside;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import spring.outside.ClassA;
@Configuration
public class AppConfiguration {
@Bean
ClassA classA() {
return new ClassA();
}
}
关于java - 如何从 spring 上下文外部将 spring bean 注册到 spring 上下文中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31740331/