Spring 为未定义的 bean 抛出异常

Posted

技术标签:

【中文标题】Spring 为未定义的 bean 抛出异常【英文标题】:Spring throws exception for undefined bean 【发布时间】:2016-03-26 09:35:40 【问题描述】:

我正在关注this tutorial 以使用 Spring Security。我想使用 Hibernate 进行数据库查询。我配置了代码,但引发了以下异常。

我在spring-security.xmlmy-servlet.xml 中定义了bean,但仍然没有结果。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myMemberDetailsService' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:570)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1114)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:279)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:320)
    ... 93 more

会员存储库

public class MemberRepositoryImpl implements MemberRepository 

    SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Override
    public Member findByUserName(String username) 

        List<Member> members = new ArrayList<Member>();
        members = sessionFactory.getCurrentSession()
                .createQuery("from Member where username=?")
                .setParameter(0, username).list();

        if (members.size() > 0) 
            return members.get(0);
         else 
            return null;
        
    


MyMemberDetailsS​​ervice

public class MyMemberDetailsService implements UserDetailsService 

    private MemberRepository memberRep;

    @Override
    public UserDetails loadUserByUsername(final String username)
            throws UsernameNotFoundException 

        Member member = memberRep.findByUserName(username);
        HashSet<String> roles = new HashSet<String>();
        roles.add("ROLE_MEMBER");
        List<GrantedAuthority> authorities = buildUserAuthority(roles);

        return buildUserForAuthentication(member, authorities);

    

    // Converts com.mkyong.users.model.User user to
    // org.springframework.security.core.userdetails.User
    private User buildUserForAuthentication(Member member,
            List<GrantedAuthority> authorities) 
        return new User(member.getUsername(), member.getPassword(),
                member.isEnabled(), true, true, true, authorities);
    

    private List<GrantedAuthority> buildUserAuthority(Set<String> userRoles) 

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        // Build user's authorities
        for (String userRole : userRoles) 
            setAuths.add(new SimpleGrantedAuthority(userRole));
        

        List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(
                setAuths);

        return Result;
    


my-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http:/www.springframework.org/schema/beans 
    http:/www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http:/www.springframework.org/schema/aop 
    http:/www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http:/www.springframework.org/schema/tx 
    http:/www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http:/www.springframework.org/schema/context
    http:/www.springframework.org/schema/mvc">


    <context:annotation-config />
    <mvc:annotation-driven />
    <mvc:view-controller path="/index" />
    <mvc:view-controller path="/" view-name="index" />
    <mvc:view-controller path="/signin" />



    <mvc:resources mapping="resources/**" location="resources/" />
    <context:component-scan base-package="com.myProject" />
    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" />
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>


    <bean id="memberRep" class="com.myProject.repository.MemberRepositoryImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>


    <bean id="myMemberDetailsService" class="com.myProject.service.MyMemberDetailsService">
        <property name="memberRep" ref="memberRep" />
    </bean>

    <!-- Hibernate Config -->

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:8889/myProject" />
        <property name="username" value="jack" />
        <property name="password" value="jack" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
        depends-on="dataSource">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.myProject.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="userServicePointCut"
            expression="execution(* com.myProject.service.*Service.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
    </aop:config>

    <!-- End Hibernate Config -->
</beans>

spring-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-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">



    <beans:import resource='login-service.xml' /> 
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/member**" access="hasRole('ROLE_MEMBER')" />
        <intercept-url pattern="/signin" access="permitAll" />


        <access-denied-handler error-page="/403" />
        <form-login login-page="/signin" default-target-url="/index"
            authentication-failure-url="/signin?error" username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" />
        <!-- enable csrf protection -->
        <csrf />
    </http>
    <authentication-manager>
        <authentication-provider user-service-ref="myMemberDetailsService">
            <password-encoder hash="bcrypt" />


        </authentication-provider>
    </authentication-manager>
</beans:beans>

【问题讨论】:

看起来你的 my-servlet.xml 文件甚至没有加载(应该在 web.xml 中定义) @kryger 我定义了 servlet-mapping 您需要将myMemberDetailsService 定义为一个bean。你有项目中示例中的 spring-database.xml 吗? @ManuZi 我没有使用它,而是在 my-servlet 和 spring-security 中定义了 bean,但都没有用。 能否在问题中包含 web.xml 文件 【参考方案1】:

刚看了教程,发现里面没有提到web.xml的配置,所以下载了看看是怎么配置的。

您说过,您尝试在 my-servletspring-security 这两个地方定义 myMemberDetailsService,但没有成功。

嗯,我认为这是配置问题,所以请尝试更改您的web.xml 如下(我使用了您在问题中使用的名称,但请检查一下是否有问题):

<servlet>
    <servlet-name>my-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/my-servlet.xml,
            /WEB-INF/spring-security.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

如果存在contextConfigLocation 参数,请删除您的全局&lt;context-param&gt;

如果这不起作用,我会建议您使用与教程类似的配置,也就是说,将最小的 MVC 配置保留在 my-servlet.xml 中,并在单独的上下文中配置其余的 bean。

希望对你有帮助!

【讨论】:

【参考方案2】:

security xml 中包含UserDetailsService 将解决此问题。

在您的 spring-security.xml 中包含 MyMemberDetailsS​​ervice 实现定义。

<beans:bean class="your.package.MyMemberDetailsService"
    id="myMemberDetailsService" />

我看到您将login-service.xml 包含在您的spring-security.xml 中。因此在login-service.xml 中定义用户服务bean 也将解决问题。

【讨论】:

【参考方案3】:

根据教程,web.xml 应该包含对您的 spring 配置 xml 的引用。

web.xml 看起来像

<servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>*</url-pattern>
    </servlet-mapping>

mvc-dispatcher-servlet xml 应该包含所有其他 xml 的导入。

mvc-dispatcher-servlet 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" 
        ...">

        <import resource="my-servlet.xml" />
        <import resource="spring-security.xml" />
        ...
    </beans>

【讨论】:

以上是关于Spring 为未定义的 bean 抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

Emscripten 为未解析的 mcount 符号抛出异常

在锁 c#2 中抛出异常

Spring抛出异常_自动装配

解析Java-throw抛出异常详细过程

Java-异常处理

未抛出 spring webflux 的自定义异常