Spring:MethodInvokingFactoryBean调用错误的方法

时间:2013-12-29 01:10:08

标签: java xml spring methods

我需要在XML中执行以下Java行:

usersConnectionRepository.setConnectionSignUp(new AccountConnectionSignUp());

所以我这样做了:

<bean id="usersConnectionRepository"
    class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
    scope="singleton">
    <constructor-arg ref="dataSource" />
    <constructor-arg ref="connectionFactoryLocator" />
    <constructor-arg ref="textEncryptor" />
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

<bean id="accountConnectionSignUp" class="edu.kit.tm.cm.ksc.config.AccountConnectionSignUp" />

<bean
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <ref local="usersConnectionRepository" />
    </property>
    <property name="targetMethod">
        <value>setConnectionSignUp</value>
    </property>
    <property name="arguments">
        <list>
            <ref local="accountConnectionSignUp" />
        </list>
    </property>
</bean>

应该调用该方法时会发生错误。

 java.lang.NoSuchMethodException: com.sun.proxy.$Proxy12.setConnectionSignUp(edu.kit.tm.cm.ksc.config.AccountConnectionSignUp)

正如您在上面所看到的,它完全在错误的包中搜索,我不知道为什么。

我不知道如何进一步调试。我对Spring缺乏经验,而且它是XML-Notation。我希望有一个人可以帮助我。谢谢。

更新

根据要求,完整的social.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:facebook="http://www.springframework.org/schema/social/facebook"
xmlns:twitter="http://www.springframework.org/schema/social/twitter"
xmlns:social="http://www.springframework.org/schema/social" xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/social/facebook http://www.springframework.org/schema/social/spring-social-facebook.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/social/twitter http://www.springframework.org/schema/social/spring-social-twitter.xsd
    http://www.springframework.org/schema/social http://www.springframework.org/schema/social/spring-social.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">


<context:property-placeholder
    location="classpath:/edu/kit/tm/cm/ksc/config/application.properties" />


<bean id="connectionFactoryLocator"
    class="org.springframework.social.connect.support.ConnectionFactoryRegistry"
    scope="singleton">
    <property name="connectionFactories">
        <list>
            <bean
                class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
                <constructor-arg value="${twitter.consumerKey}" />
                <constructor-arg value="${twitter.consumerSecret}" />
            </bean>
            <bean
                class="org.springframework.social.facebook.connect.FacebookConnectionFactory">
                <constructor-arg value="${facebook.clientId}" />
                <constructor-arg value="${facebook.clientSecret}" />
            </bean>
        </list>
    </property>
    <aop:scoped-proxy proxy-target-class="false" />
</bean>



<bean id="usersConnectionRepository"
    class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
    scope="singleton">
    <constructor-arg ref="dataSource" />
    <constructor-arg ref="connectionFactoryLocator" />
    <constructor-arg ref="textEncryptor" />
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

<bean id="accountConnectionSignUp" class="edu.kit.tm.cm.ksc.config.AccountConnectionSignUp" />

<bean
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <ref local="usersConnectionRepository" />
    </property>
    <property name="targetMethod">
        <value>setConnectionSignUp</value>
    </property>
    <property name="arguments">
        <list>
            <ref local="accountConnectionSignUp" />
        </list>
    </property>
</bean>

<bean id="connectionRepository" factory-method="createConnectionRepository"
    factory-bean="usersConnectionRepository" scope="request">
    <constructor-arg value="#{request.userPrincipal.name}" />
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

<mvc:annotation-driven />
<bean
    class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />


<bean class="org.springframework.social.connect.web.ConnectController">
    <!-- relies on by-type autowiring for the constructor-args -->
    <!-- <constructor-arg ref="connectionFactoryLocator" /> -->
    <!-- <constructor-arg ref="connectionRepository" /> -->
</bean>


<bean id="SimpleSignInAdapter" class="edu.kit.tm.cm.ksc.config.SimpleSignInAdapter" />

<bean class="org.springframework.social.connect.web.ProviderSignInController">
    <!-- relies on by-type autowiring for the constructor-args -->
    <constructor-arg ref="SimpleSignInAdapter" />
</bean>

更新2

我们将Spring-Social-Documentation的Java示例写入XML。在这种情况下,ProviderSigninControllers依赖项。不幸的是,在这种情况下没有给出XML示例。

1 个答案:

答案 0 :(得分:2)

简单的解决方案是在proxy-target-class bean定义中将usersConnectionRepository更改为true,并将CGLIB添加到类路径中。

如果您不需要代理,请将其彻底删除。

说明:

首先,使用此bean声明

<bean id="usersConnectionRepository"
    class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository"
    scope="singleton">
    <constructor-arg ref="dataSource" />
    <constructor-arg ref="connectionFactoryLocator" />
    <constructor-arg ref="textEncryptor" />
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

Spring正在创建一个类型为JdbcUsersConnectionRepository的bean并将其包装在JDK代理中(因为proxy-target-classfalse)。 JDK代理的严重缺点是它们只是子类型接口。

换句话说,Spring将看到JdbcUsersConnectionRepository类实现UsersConnectionRepository接口并在生成代理时使用它。正如javadoc所说

  
      
  • 代理类扩展了java.lang.reflect.Proxy。
  •   
  • 代理类完全实现在创建时指定的接口   同样的订单。
  •   

因此生成的代理将是ProxyUsersConnectionRepository类型。

MethodInvokingFactoryBean这不是问题,因为它将引用存储在Object类型的字段中。但是,当MethodInvokingFactoryBean尝试解析要调用的Method时,它会使用目标对象的Class实例,即。 object.getClass()。由于目标对象实际上是Proxy类型,或者com.sun.proxy.$Proxy12是准确的,因此它没有JdbcUsersConnectionRepository#setConnectionSignUp方法并导致NoSuchMethodException