java - Spring:ApplicationContextAware 有价值,但@Autowired 没有
问题描述
几个小时前我打开了一个问题,它被标记为重复,但它不是标记问题的重复,无论如何。
从那以后,我设法完成了一些事情,并解决了一些问题,所以这是我的问题:
我试图将一个spring bean @Autowire 放入另一个spring bean,但是我的问题是@Autowired 字段始终为空,尽管它们都是托管bean 并且它们自己可以正常工作。
我发现,您可以通过实现 ApplicationContextAware 接口来访问 bean 中的 ApplicationContext,我这样做了。它被调用并被赋予了正确的上下文。
这样,我可以在上下文中调用 getBean() ,它首先返回我想要 @Autowire 的 bean,这很不错,但这似乎是解决更大问题的一种解决方法。
你能帮我出什么问题吗?我尝试将@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";
}
}
提前致谢。
解决方案
好的,我明白了...男孩确实花了一些时间。
因此,事实证明,我描述的上下文不包括导致问题的上下文,但我不想用我的整个模块向线程发送垃圾邮件。
缺少的部分是我正在远程处理这些 bean,只是那些在自动装配上有问题的 bean(当时我不知道)。
我远程控制它们的方式是我为BeanDefinitionRegistryPostProcessor编写了一个实现。
这样做的问题是我在调用接口的函数后立即实例化了远程 bean,这意味着:在 Spring 通常会实例化我想要远程的 bean 之前 => 太早了。
我过早调用 getBean() 意味着在实例化 bean 时,AutowiredCapableBeanPostProcessor(或像这样的 sg.)没有在工厂列表中注册,我也无法控制它。
====================================TL;DR============ ======================
解决方案是在 Remote Exporter bean 中,当调用postProcessBeanDefinitionRegistry()函数时,我只是简单地保存了注册表,并实现了InstantiationAwareBeanPostProcessor并在调用postProcessAfterInstantiation()时进行了实际的远程处理=> 当 bean 被实例化时“正常”方式 => 将完成自动装配,并创建远程 bean。
很抱歉占用了你的时间,我真的很感激。
推荐阅读
- svg - 可以在 SVG 文件中使用 IEEE 754 格式的浮点来获得精度
- python - 如何在两次交换数字后停止交换列表
- google-apps-script - 更改所有工作表中的电子邮件
- python - 无法在 Mac 上下载 Pygame
- javascript - 如何在带有 Nedb 的 node.js 中使用变量作为点符号地址?TypeError'无法读取未定义的属性'find'
- for-loop - Boto3 get_bucket_location 返回:使用变量时拒绝访问
- c++ - 如何调试非常慢(200 秒)的 fwrite()/ftello()/fclose()?
- android - 如果 Android 应用程序不在中国 Android 手机的堆栈中,则推送通知不起作用
- node.js - 节点如何同时处理多个请求?
- c# - 如何将此源变量绑定到现有文本框?