如何使用已经在另一个 .xml 文件中配置的 bean?

Posted

技术标签:

【中文标题】如何使用已经在另一个 .xml 文件中配置的 bean?【英文标题】:How to use bean that is already configured in another .xml file? 【发布时间】:2016-01-05 05:55:07 【问题描述】:

我正在尝试关注 this example 关于 Spring Security 并使其适应我的需求,但我在配置方面遇到了问题

我有一个LoginService,看起来像这样:

// This example does not make sense of course but I'm just
// trying to make it work with @PreAuthorize("hasRole('ROLE_ADMIN')")
// and see an exception or something that lets me know that
// it is actually working ..

public class LoginService 

    private final static Logger LOGGER = Logger.getLogger(LoginService.class.getName());

    private AdministratorRepository administratorRepository;

    public LoginService(DSLContext ctx)        
        this.administratorRepository = new AdministratorRepository(ctx);
    

    @Transactional
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void login(String userId, String password)      
        LOGGER.debug("Login for " + userId);        
        this.administratorRepository.login(userId, password);   
    


我已经在我的 applicationContext-jooq.xml 中初始化这个类,如下所示:

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

<!-- Configure Spring's transaction manager to use a DataSource -->
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- Configure jOOQ's TransactionProvider as a proxy to Spring's transaction manager -->
<bean id="transactionProvider"
    class="com.mz.server.web.SpringTransactionProvider">
</bean>

<!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
     which can dynamically discover the transaction context -->
<bean id="transactionAwareDataSource"
    class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <constructor-arg ref="dataSource" />
</bean>

<bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider">
    <constructor-arg ref="transactionAwareDataSource" />
</bean>

<!-- Configure the DSL object, optionally overriding jOOQ Exceptions with Spring Exceptions -->
<bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
    <constructor-arg ref="config" />
</bean>

<!-- Invoking an internal, package-private constructor for the example
     Implement your own Configuration for more reliable behaviour -->
<bean class="org.jooq.impl.DefaultConfiguration" name="config">
    <property name="SQLDialect"><value type="org.jooq.SQLDialect">POSTGRES_9_4</value></property>
    <property name="connectionProvider" ref="connectionProvider" />
    <property name="transactionProvider" ref="transactionProvider" />
</bean>

<!-- BEGIN Services -->

<bean id="loginService" class="com.mz.server.web.service.LoginService">
    <constructor-arg>
        <ref bean="dsl" />
    </constructor-arg>
</bean>

<!-- END Services -->

我的问题是我希望 loginService 也由 Spring Security 管理。这是我的 applicationContext-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />

    <http auto-config="true" >
        <intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
    </http>

    <authentication-manager >
        <authentication-provider>
            <user-service>
                <user name="admin" password="admin" authorities="ROLE_ADMIN" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

<!-- <beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/> -->

</beans:beans>

如果我注释掉

<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>

我收到没有默认构造函数的错误 - 这是真的,因为这个类是 1. 已经实例化并且 2. 需要一个 DSLContext 对象作为构造函数参数。

如果我让它注释掉,什么都不会发生。不显示警告例外。 @PreAuthorize 似乎被忽略了..

我该如何解决这个问题?

【问题讨论】:

applicationContext-securityapplicationContext-jooq 是否加载在同一个上下文中? @M.Deinum 老实说,我无法回答这个问题。我怎么知道他们是不是?基本上 applicationContext-security.xml 应该只包含与 Spring 相关的 bean,而 applicationContext-jooq 只描述了我的数据库连接的工作方式。如何判断它们是否在相同的上下文中加载? 如果它们都加载了COntextLoaderListener,那么如果其中一个加载了DispatcherServlet,它将无法工作。另一件事是您没有接口,因此您可能需要在 global-method-security 元素上将 proxy-target-class 设置为 true 我还建议阅读 Spring 的工作原理,尤其是 ApplicationContext 的配置如何工作。 【参考方案1】:

您可以在 LoginService 的 XML 配置中添加构造函数注入。你也自动接线DSLContext 吗?

您的 XML 中的这一行正在调用 default 构造函数:

<beans:bean name="loginService" class="com.mz.server.web.service.LoginService"/>

如果你想对 DSLContext 进行构造函数注入,它看起来像这样:

<bean name="loginService" class="com.mz.server.web.service.LoginService">
    <constructor-arg ref="dslContext"/>
</bean>

这假定 bean 工厂也有一个 bean 用于您的 DSLContext

你也可以尝试去所有的注解或者XML配置,但是不要混用和匹配。

【讨论】:

DSLContextapplicationContext-jooq.xml 中作为构造函数参数传递(见上文) - 您是指 构造函数注入 吗? 查看我的更新答案:当你正确执行它时,它完全具有构造函数注入的样子。 我不明白。这就是我在 applicationContext-jooq.xml 中所做的? 看豆厂说你弄错了。检查你的假设。如果你只是假设你做的一切都是正确的,而 Spring 正在迫害你,那么你就没有任何进展。有一个配置,您要求在没有默认塞浦路斯的地方。修复它。 好的。但我的问题不在于我不知道如何将DSLContext 传递给LoginService。我的问题是我不知道我该怎么做在我的 applicationContext-security.xml 中重用 applicationContext-jooq.xml 中已经描述的 bean &lt;bean id="dsl" ...&gt;。您的建议是,我只需将配置从 -jooq.xml 复制并粘贴到 -security.xml 并使用dsl,就像我已经在使用它一样.我的问题旨在避免在两个不同的配置文件中为 bean 提供完全相同的配置。

以上是关于如何使用已经在另一个 .xml 文件中配置的 bean?的主要内容,如果未能解决你的问题,请参考以下文章

Magento 2 - 如何在另一个 phtml 文件、xml 布局、静态块和 cms 页面中调用自定义 phtml 文件?

Java--IDEA中Spring配置错误:class path resource [.xml] cannot be opened because it does not exist

java.io.FileNotFoundException class path resource [xxx.xml] cannot be opened

Spring 自动装配

在另一个项目中添加 Slow Cheetah 转换的配置文件作为参考

使用c#在另一台计算机中读取xml文件