提问者:小点点

如何从外部将Spring bean注册到Spring上下文中?


我有以下组件

  • 使用SpringMVC(war文件)公开的Web应用程序。
  • 一个库(jar-file),它知道无论谁在使用这个库,都使用Spring。

场景

我的库有一个类需要将自己注册为Web应用程序上下文中的bean,而无需告诉库的用户更改他们的代码(xml、Spring上下文或类)。

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

我所尝试的

>

  • 使用BeanFactoryPostProcator,但这需要我访问应用程序上下文并尽可能地调用addBeanFactoryPostProcess。

    使用ApplicationContextFirst alizer,但这迫使我更改web. xml

    一大堆其他的东西,比如不同的Aware接口,但是我还没有找到任何允许我的类自我注册到Bean Factory并在Spring上下文中被拾取的东西,我希望能够使用像调度注释这样的东西。而且我总是希望Spring上下文中的其他人能够通过自动标注找到我的类。

    例子

    我自己的班级和我的图书馆

    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());
        }
    }
    

    尝试过了

    • 使用BeanFactoryPostProcator和寄存器Singleton添加它
    • 使用ApplicationContextCentalizer添加它,然后使用addBeanFactoryPostProcator与BeanFactoryPostProcator结合使用
    • 通过BeanUtils. instantiate添加它
    • 通过实现ApplicationContextAware并将其转换为ConfigurableApplicationContext并添加BeanFactoryPostPrecator实现来添加它,我还尝试将类型转换为ConfigurableListableBeanFactory并注册Singleton。
    • 使用BeanFactoryAware添加它并注册Singleton。
    • 将我的ClassC添加到一个配置中,在该配置中,我添加了组件Scan用于Spring. out包,效果非常好,但这样做感觉非常错误。

    但是所有这些似乎都是部分工作的,但是它总是会得到一些时间错误,比如: ClassA需要在ClassC内部自动装配的构造函数中输入变量,其中一些是在ClassC创建ClassA时设置的。我看到的另一个场景是ClassB无法自动装配ClassA,因为那是以前做过的。那么,什么是正确和好的方法呢?

    我正在运行Spring版本3.2.11。释放

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

    谢谢和最好的问候!


  • 共1个答案

    匿名用户

    在这种情况下,您必须在Spring Context中包含ClassA作为Spring beanXML

    <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();
        }
    }