Spring:ApplicationContextAware有价值,但@Autowired没有

时间:2018-05-21 03:30:07

标签: java spring spring-boot

我在几个星期前打开了一个问题,这个问题被标记为重复,但是它不是标记问题的重复,无论如何。

从那时起,我设法完成了一些工作,然后解决了问题,所以这是我的问题:

我试图@Autowire一个spring bean到另一个,但我的问题是@Autowired字段总是为null,表明它们都是托管bean并且自己正常工作。

我发现,你可以通过实现ApplicationContextAware接口来访问bean中的ApplicationContext,我这样做了。它被称为正确的背景。

这样,我可以在上下文中调用getBean(),它首先返回我想要@Autowire的bean,这是一个yaay,但这似乎是一个更大问题的解决方法。

你可以帮我解决可能出错的问题吗?我尝试@Autowiring作为字段,方法和构造函数参数,没有工作。这些bean都是单例bean,用作HesianServiceExporter的基础,以便从另一个servlet访问它们。

我想我在这里缺少一些重要的配置信息,但是我不明白为什么现场注入不起作用,同时接口实现也是如此。 这是一个案例,我想要@Autowire的bean还没有准备好,所以它不能被注入?

正如你们中的一些人所要求的,这是我的代码。不知道它有什么帮助,但是:

@Service(Persistence.NAME)
public class PersistenceBean implements Persistence, ApplicationContextAware {

ApplicationContext context;

@Override
public User getUser() {
    User user = new User();
    user.setEmail(context.getBean(HelloWorld.class).getText());
    return user;
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

我的context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context https://www.springframework.org/context/spring-context.xsd
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


<context:annotation-config />
<context:component-scan base-package="hu.bme.sch.qpa" annotation-config="true"/>

<bean id="sessionFactory"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource"
              ref="dataSource"/>
    <property name="packagesToScan"
              value="hu.bme.sch.qpa.global.entities"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">
                update
            </prop>
            <prop key="hibernate.dialect">
                org.hibernate.dialect.PostgreSQL95Dialect
            </prop>
        </props>
    </property>
</bean>

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.postgresql.Driver"/>
    <property name="url" value="jdbc:postgresql://localhost:5432/test"/>
    <property name="username" value="qpapp_server_user"/>
    <property name="password" value="root"/>
</bean>

<bean id="txManager"
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>

<bean id="persistenceExceptionTranslationPostProcessor" class=
        "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

</beans>

最后,我的ApplicationInitializer注释如下:

@ImportResource("/WEB-INF/app-core-servlet.xml")
@SpringBootApplication(scanBasePackages = "hu.bme.sch.qpa")
@EnableWebMvc
@Configuration
@EnableAutoConfiguration
public class CoreStarter extends SpringBootServletInitializer {

public static void main(String[] args) throws Exception {
    SpringApplication.run(CoreStarter.class, args);
}

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);

    }
}

这是HelloWorld bean,它是(顾名思义)一个非常简单的bean。它与PersistenceBean在同一个包中:

@Service(HelloWorld.NAME)
public class HelloWorldBean implements HelloWorld {

@Override
public String getText() {
    return "Hello World!!!! I'm remoted";
}
}

提前致谢。

1 个答案:

答案 0 :(得分:0)

好的,我明白了......男孩花了一些时间。

因此,事实证明,我描述的上下文并没有包含引起问题的上下文,但我并不想用我的整个模块发送垃圾邮件。

缺少的部分是我正在远程处理这些豆子,只是那些在自动装配方面遇到麻烦的人(当时我当时并不知道)。

我改编它们的方式是我在 BeanDefinitionRegistryPostProcessor 中编写了一个实现。

这个问题是我在调用接口函数后立即实例化了远程bean,这意味着:在Spring通常会实例化我想要远程的bean =&gt;太早了。

我过早地调用getBean()意味着在实例化bean时,AutowiredCapableBeanPostProcessor(或者像这样的sg)没有在工厂列表中注册,我也没有控制它。

=================================== TL; DR ========= ========================

解决方案是在Remote Exporter bean中,当调用 postProcessBeanDefinitionRegistry()函数时,我只是保存了注册表,并实现了 InstantiationAwareBeanPostProcessor 并完成了调用 postProcessAfterInstantiation()时的实际远程处理=&gt;当bean被实例化时,&#34;正常&#34; way =&gt;将完成自动装配,以及将创建远程bean。

抱歉偷了你的时间,我真的很感激。