在 Spring 4.3.5 中,我们一直在使用一种应用程序架构,在该架构中我们一次性初始化一些 bean,然后将这些 bean 用作其他 bean 的“参考”。
像这样的东西
<bean id="handleUncheckedEndpointExceptionAdvice"
class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
<constructor-arg ref="exceptionFactory"/>
<property name="exceptionSenderService" ref="exceptionSenderService" />
</bean>
但是一旦我们将库升级到 Spring 5.2.x,我们开始在 Jboss 7.3.1 启动时遇到以下异常:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handleUncheckedEndpointExceptionAdvice' defined in ServletContext resource [/WEB-INF/context-web.xml]: Cannot resolve reference to bean 'exceptionSenderService' while setting bean property 'exceptionSenderService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'exceptionSenderService' available
我所做的一切:
启用 TRACE 日志记录并发现这一点 -2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.InjectionMetadata] (ServerService Thread Pool -- 65) Processing injected element of bean 'exceptionSenderService': AutowiredFieldElement for private com.gehcit.cp.serviceability.service.ExceptionSenderService com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl.exceptionSender 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.support.DefaultListableBeanFactory] (ServerService Thread Pool -- 65) Returning cached instance of singleton bean 'exceptionSenderServiceImpl' 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] (ServerService Thread Pool -- 65) Autowiring by type from bean name 'exceptionSenderService' to bean named 'exceptionSenderServiceImpl'
现在 bean 正在初始化,但是当搜索引用时,从 Spring 缓存中搜索,我们什么也得不到。
但是后来我们尝试将 bean 初始化从不同的 xml 转移到 bean 被引用的相同 xml 并且有效。所以我们得出结论,不知何故,跨 XML 配置不起作用。
从 context-web.xml 引用的 Bean
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/security/oauth2
https://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<task:annotation-driven/>
<!-- Define placeholder for application properties -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/web.properties</value>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
<!-- Load CXF modules from cxf.jar -->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<import resource="context-cem-web.xml"/>
<!-- define an auto-proxy generator for our advisors -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="false"/>
</bean>
<!-- id generator for exceptions -->
<bean id="exceptionIdGenerator"
class="com.gehcit.cp.ws.infrastructure.exception.HostTimeExceptionIdGenerator">
<property name="prefix" value="CEN"/>
</bean>
<!-- system fault factory -->
<bean id="systemFaultFactory"
class="com.gehcit.cp.ws.infrastructure.exception.StandardSystemFaultFactory">
<property name="exceptionIdGenerator" ref="exceptionIdGenerator"/>
<property name="appendExceptionIdToErrorMessage" value="true"/>
</bean>
<bean id="defaultParamConverterProvider"
class="org.apache.cxf.jaxrs.ext.search.DefaultParamConverterProvider"/>
<!-- factory for mapping runtime exceptions to wire faults -->
<bean id="exceptionFactory"
class="com.gehcit.cp.ws.infrastructure.exception.ExceptionMapperExceptionFactory">
<property name="exceptionMappers">
<list>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.IllegalArgumentFaultFromIllegalArgumentExceptionMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.SecurityFaultFromCPSecurityExceptionMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.ApplicationFaultFromApplicationErrorMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.SystemFaultFromRuntimeExceptionMapper">
<constructor-arg ref="systemFaultFactory"/>
</bean>
</list>
</property>
</bean>
<!-- aspect for handling unchecked endpoint exceptions -->
<bean id="handleUncheckedEndpointExceptionAdvice"
class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
<constructor-arg ref="exceptionFactory"/>
<property name="exceptionSenderService" ref="exceptionSenderService" />
</bean>
<bean id="handleUncheckedEndpointExceptionPointcut"
class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
<constructor-arg type="java.lang.Class">
<null/>
</constructor-arg>
<constructor-arg type="java.lang.Class"
value="com.gehcit.cp.ws.infrastructure.aop.annotations.HandleUncheckedEndpointException"/>
</bean>
<bean id="handleUncheckedEndpointExceptionAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="handleUncheckedEndpointExceptionAdvice"/>
<property name="pointcut"
ref="handleUncheckedEndpointExceptionPointcut"/>
</bean>
bean 正在 context-applix.xml 中初始化
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<!-- Activemq connection factory start -->
<bean id ="connectionAmqFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL"
value="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"
/>
</bean>
<!-- A POJO that implements the JMS message listener -->
<bean id="aplixSubscriberQueueService"
class="com.gehcit.cp.cem.aplix.jms.listener.AplixSubscriberQueueListener"
/>
<bean id="exceptionSenderService"
class="com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl"
/>
<!-- A destination in ActiveMQ -->
<!--amq:topic id="destination" physicalName="APLIX.ERRORINFO" /-->
<!-- A destination in ActiveMQ -->
<amq:queue id="destination" physicalName="APLIX.ERRORINFO" />
<!-- A destination in ActiveMQ end-->
<!-- A cached connection to wrap the ActiveMQ connection -->
<bean id="cachedAmqConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory"
p:targetConnectionFactory-ref="connectionAmqFactory"
p:sessionCacheSize="10" />
<!-- Adding JMS transaction Manager -->
<bean id="TransactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="cachedAmqConnectionFactory"/>
</bean>
<!-- Adding JMS transaction Manager -End -->
<!-- A JmsTemplate instance that uses the connection and destination -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="cachedAmqConnectionFactory"
p:defaultDestination-ref="destination" />
<!-- A JmsTemplate instance that uses the connection and destination end -->
<!--Cofiguring JMS container and listener-->
<jms:listener-container container-type="default"
connection-factory="cachedAmqConnectionFactory" destination-type="queue" >
<jms:listener destination="APLIX.ERRORINFO"
ref="aplixSubscriberQueueService" method="onMessage" />
</jms:listener-container>
<!--Cofiguring JMS container and listener end-->
<!-- The Spring message listener container configuration -->
<amq:broker start="true" persistent="false"
brokerName="broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"
deleteAllMessagesOnStartup="false" >
<amq:managementContext>
<amq:managementContext createConnector="false"/>
</amq:managementContext>
<amq:systemUsage>
<amq:systemUsage>
<amq:memoryUsage>
<amq:memoryUsage limit="512 mb"/>
</amq:memoryUsage>
<amq:tempUsage>
<amq:tempUsage limit="2 gb"/>
</amq:tempUsage>
</amq:systemUsage>
</amq:systemUsage>
<amq:transportConnectors>
<amq:transportConnector name="vm"
uri="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"/>
</amq:transportConnectors>
</amq:broker>
</beans>
有人可以帮我找到一种方法来引用 Spring 5.2.x 中其他 xml 文件中的 bean。 注意:我们已经用 Spring 5.2 更改了类加载部分。
将此添加到 web.xml
<listener-class>com.gehcit.cp.ws.infrastructure.security.BeanFactoryContextLoaderListener</listener-class>
</listener>
<!-- <context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>/beanRefFactory.xml</param-value>
</context-param> -->
BeanFactoryContextLoaderListener.java
package com.gehcit.cp.ws.infrastructure.security;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
public class BeanFactoryContextLoaderListener extends ContextLoaderListener {
private static Logger log = Logger.getLogger(BeanFactoryContextLoaderListener.class)
@Override
protected ApplicationContext loadParentContext(ServletContext servletContext) {
log.info("Entered loadParentContext");
ApplicationContext ctx = new ClassPathXmlApplicationContext("beanRefFactory.xml");
log.info("Exit loadParentContext" + ctx.toString());
return ctx;
}
}