如何从spring spring上下文中将spring bean注册到spring上下文中?

时间:2015-07-31 07:20:47

标签: java spring applicationcontext spring-bean

我有以下组件

  • 使用Spring MVC(war文件)公开的Web应用程序。
  • 一个库(jar文件),它知道使用该库的人使用spring。

方案

我的库有一个类需要将自己注册为Web应用程序上下文中的bean,而不会告诉库的用户更改其代码(xml,spring context或classes)。

所以,换句话说,我有一个Class和一个spring上下文,我只希望我的类在这个spring上下文中注册而不改变其中的任何内容。 那么有没有时间spring会扫描类路径以实现某个接口的类,如果有的话接口是什么?

我尝试了什么

  • 使用BeanFactoryPostProcessor但这要求我访问应用程序上下文并尽可能地调用addBeanFactoryPostProcessor。

  • 使用ApplicationContextInitializer但这迫使我更改web.xml

  • 其他一些东西,比如不同的Aware接口,但我还没有找到任何允许我的类自我注册到Bean Factory并在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"/>

如果这是不可能的我想探索一下我在班级里面可以做些什么的可能性,尽可能容易地告诉弹簧背景来拾取它。

实施例

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内部自动装配的构造函数中的输入变量,其中一些是在ClassC创建ClassA时设置的。我看到的另一个场景是ClassB无法使用Autowired ClassA,因为之前已经完成了。那么这样做的正确和好的方法是什么?

我正在运行 spring version 3.2.11.RELEASE

如果有人知道如何以一种很好的方式解决这个问题,而不是那种感觉像“丑陋的黑客”的东西,我会很高兴知道!

谢谢和最诚挚的问候!

1 个答案:

答案 0 :(得分:2)

在这种情况下,您必须在Spring上下文xml

中包含ClassA作为spring bean
<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();
    }
}