英文:
Spring Filter components in auto scanning
问题
我有一个 Spring MVC 应用程序(一个面向 Java 平台的应用程序框架和控制反转容器)。该框架的核心功能可用于任何 Java 应用程序,但也有用于在 Java EE(企业版)平台上构建 Web 应用程序的扩展),使用了 Spring 过滤功能,现在使用 Spring 过滤器。
<context:component-scan base-package="com.pastis">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="regex" expression="com.pastis.pq.workflow.web.*" />
<context:exclude-filter type="regex" expression="com.pastis.security.*" />
<context:exclude-filter type="regex" expression="com\.pastis\.security\..*" />
</context:component-scan>
<jpa:repositories base-package="com.pastis.repositories"/>
还尝试过:
<context:annotation-config />
<context:component-scan base-package="com.pastis">
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<context:component-scan base-package="com.pastis.pq">
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowAdminController"/>
</context:component-scan>
</context:component-scan>
但是我在 WorkflowController
中遇到了问题,并且这个控制器:
com.pastis.security.controller.SecurityManagerController
然而,当我启动应用程序时,我得到了以下错误:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityManagerController':
在 servlet 配置文件中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 使用注解注入依赖 -->
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" use-default-filters="false" >
<context:include-filter type="aspectj" expression="com.pastis.pq.web.endpoint.*" />
<!--context:include-filter type="annotation" expression="com.pastis.pq.web."/--><!-- 这一行被注释掉了 -->
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<!-- 主数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:~/test2;DB_CLOSE_DELAY=-1" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- 事务管理 -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Spring Data 仓库 -->
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="pastis-entities" />
<property name="packagesToScan">
<array>
<value>com.pastis.pq.model</value>
</array>
</property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="eclipselink.target-database">org.eclipse.persistence.platform.database.OraclePlatform</prop>
<prop key="eclipselink.target-server">WebLogic</prop>
</props>
</property>
</bean>
<!-- 可自定义的数据库配置 -->
<bean id="dataConfig" class="com.pastis.commons.services.SystemConfig">
<constructor-arg index="0" value="test-config.properties"/>
<constructor-arg index="1" ref="dataSource"/>
</bean>
</beans>
在运行测试时的控制台输出:
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - 创建共享的 singleton bean 实例 'securityManagerController'
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - 创建共享的 singleton bean 实例 'securityManagerController'
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - 创建 bean 'securityManagerController' 的实例
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - 创建 bean 'securityManagerController' 的实例
2020-10-08 10:46:57,317 [DEBUG] org.springframework.beans.factory.annotation.InjectionMetadata - 在类 [com.pastis.security.controller.SecurityManagerController] 上注册了注入元素:
英文:
I have a Spring MVC app. ( an application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE (Enterprise Edition) platform) using this Spring filtering, Now using spring filter
<context:component-scan base-package="com.pastis" >
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="regex" expression="com.pastis.pq.workflow.web.*" />
<context:exclude-filter type="regex" expression="com.pastis.security.*" />
<context:exclude-filter type="regex" expression="com\.pastis\.security\..*" />
</context:component-scan>
<jpa:repositories base-package="com.pastis.repositories"/>
also tried:
<context:annotation-config />
<context:component-scan base-package="com.pastis" />
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<context:component-scan base-package=" com.pastis.pq">
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowAdminController"/>
</context:component-scan>
but I have a problem with the WorkflowController
and this controller:
com.pastis.security.controller.SecurityManagerController
nevertheless when I start the app. I got this error:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityManagerController':
the servlet-xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Use annotations to inject stuff -->
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" use-default-filters="false" >
<context:include-filter type="aspectj" expression="com.pastis.pq.web.endpoint.*" />
<!--context:include-filter type="annotation" expression="com.pastis.pq.web."-/-->
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<!-- main datasource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:~/test2;DB_CLOSE_DELAY=-1 />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- transaction management -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- spring data repositories -->
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="pastis-entities" />
<property name="packagesToScan">
<array>
<value>com.pastis.pq.model</value>
</array>
</property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="eclipselink.target-database">org.eclipse.persistence.platform.database.OraclePlatform</prop>
<prop key="eclipselink.target-server">WebLogic</prop>
</props>
</property>
</bean>
<!-- customizable database configuration -->
<bean id="dataConfig" class="com.pastis.commons.services.SystemConfig">
<constructor-arg index="0" value="test-config.properties"/>
<constructor-arg index="1" ref="dataSource"/>
</bean>
</beans>
the console when I run the tests:
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'securityManagerController'
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'securityManagerController'
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'securityManagerController'
2020-10-08 10:46:57,315 [DEBUG] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'securityManagerController'
2020-10-08 10:46:57,317 [DEBUG] org.springframework.beans.factory.annotation.InjectionMetadata - Registered injected element on class [com.pastis.security.controller.SecurityManagerController]:
答案1
得分: 0
你的初始代码片段是正确的,但是你没有为组件扫描定义正确的包。
如果你要排除的类是这个:
com.pastis.security.controller.SecurityManagerController
而不是这个 XML 片段:
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" >
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
你需要做类似这样的更改:
<context:annotation-config />
<context:component-scan base-package="com.pastis">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
请注意,将包名从 com.pastis.pq
更改为 com.pastis
。
或者更好的做法是为此目的定义另一个 component-scan
元素:
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" />
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
请不要忘记从 <context:component-scan>
元素中删除属性 use-default-filters="false"
。如 文档 中所示:
> 您还可以通过在注解上设置 useDefaultFilters=false
或在 <component-scan/>
元素的属性中提供 use-default-filters="false"
来禁用默认过滤器。这实际上会禁用自动检测使用 @Component
、@Repository
、@Service
、@Controller
或 @Configuration
注解的类。
这很可能是你尝试的某种方法中,Spring 无法识别 com.pastis.pq.web.endpoint.*
包中的 bean 的原因。
只要你使用了 <context:component-scan>
,可能你可以去掉 <context:annotation-config>
元素。请参阅 这个很棒的回答。
更新
在问题的不同更改后,我认为这个 XML 配置应该可以正常工作:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.pastis.pq">
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowAdminController"/>
</context:component-scan>
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<!-- 主数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:~/test2;DB_CLOSE_DELAY=-1" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- 事务管理 -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Spring 数据仓库 -->
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="pastis-entities" />
<property name="packagesToScan">
<array>
<value>com.pastis.pq.model</value>
</array>
</property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="eclipselink.target-database">org.eclipse.persistence.platform.database.OraclePlatform</prop>
<prop key="eclipselink.target-server">WebLogic</prop>
</props>
</property>
</bean>
<!-- 可自定义的数据库配置 -->
<bean id="dataConfig" class="com.pastis.commons.services.SystemConfig">
<constructor-arg index="0" value="test-config.properties"/>
<constructor-arg index="1" ref="dataSource"/>
</bean>
</beans>
英文:
Your initial code snippet is right, but you are not defining the right package for component scanning.
If the class you want to exclude is this:
com.pastis.security.controller.SecurityManagerController
Instead of this XML fragment:
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" >
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
You need something like:
<context:annotation-config />
<context:component-scan base-package="com.pastis">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
Please, notice the change in the package name from com.pastis.pq
to com.pastis
.
Or better, define another component-scan
element for that purpose:
<context:annotation-config />
<context:component-scan base-package="com.pastis.pq" />
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
Please, do not forget to remove the attribute use-default-filters="false"
from the <context:component-scan>
element. As indicated in the documentation:
> You can also disable the default filters by setting useDefaultFilters=false
on the annotation or providing use-default-filters="false"
as an attribute of the <component-scan/>
element. This will in effect disable automatic detection of classes annotated with @Component
, @Repository
, @Service
, @Controller
, or @Configuration
.
This is very likely the reason why in one of the approaches you tried Spring was unable to identify the beans in your com.pastis.pq.web.endpoint.*
package.
As long as you are using <context:component-scan>
, probably you can get rid of the <context:annotation-config>
element. Please, see this great answer here in stackoverflow.
UPDATE
After the different changes in the question, I think that this XML configuration should work properly:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.pastis.pq">
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowController"/>
<context:exclude-filter type="assignable" expression="com.pastis.pq.workflow.web.controller.WorkflowAdminController"/>
</context:component-scan>
<context:component-scan base-package="com.pastis.security">
<context:exclude-filter type="assignable" expression="com.pastis.security.controller.SecurityManagerController"/>
</context:component-scan>
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<!-- main datasource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:~/test2;DB_CLOSE_DELAY=-1 />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- transaction management -->
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- spring data repositories -->
<jpa:repositories base-package="com.pastis.pq.repositories"/>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="pastis-entities" />
<property name="packagesToScan">
<array>
<value>com.pastis.pq.model</value>
</array>
</property>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="eclipselink.target-database">org.eclipse.persistence.platform.database.OraclePlatform</prop>
<prop key="eclipselink.target-server">WebLogic</prop>
</props>
</property>
</bean>
<!-- customizable database configuration -->
<bean id="dataConfig" class="com.pastis.commons.services.SystemConfig">
<constructor-arg index="0" value="test-config.properties"/>
<constructor-arg index="1" ref="dataSource"/>
</bean>
</beans>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论