problem in Spring session scope bean with AOP

2020-03-06 02:14发布

问题:

I want to inject currentUser instance in HomeController class. so for every request, HomeController will have currentUser object.

My configuration:

<bean id="homeController" class="com.xxxxx.actions.HomeController">
    <property name="serviceExecutor" ref="serviceExecutorApi"/>
    <property name="currentUser" ref="currentUser"/>
</bean>

<bean id="userProviderFactoryBean" class="com.xxxxx.UserProvider">
    <property name="userDao" ref="userDao"/>
</bean>

<bean id="currentUser" factory-bean="userProviderFactoryBean" scope="session">
    <aop:scoped-proxy/>
</bean>

But I am getting following error.

Caused by: java.lang.IllegalStateException: Cannot create scoped proxy for bean 'scopedTarget.currentUser': Target type could not be determined at the time of proxy creation.
        at org.springframework.aop.scope.ScopedProxyFactoryBean.setBeanFactory(ScopedProxyFactoryBean.java:94)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1350)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:540)

What is the problem? and Is there any better/simple alternative?

Cheers.

回答1:

With scoped-proxies, Spring still needs to know the type of the bean when the context is initialized, and in this case it's failing to do so. You need to try and give it more information.

I notice that you're only specifying factory-bean in your definition of currentUser, with no factory-method specified. I'm actually rather surprised that that's a valid definition, since the two are normally used together. So try adding the factory-method attribute to currentUser, which specifies the method on userProviderFactoryBean which creates the user bean. That method needs to have a return type of your User class, which Spring will use to infer the type of currentUser.


Edit: OK, after your comment below, it seems you've misunderstood how to use factory beans in Spring. When you have a bean of type FactoryBean, you don't need to use the factory-bean attribute as well. So instead of this:

<bean id="userProviderFactoryBean" class="com.xxxxx.UserProvider">
    <property name="userDao" ref="userDao"/>
</bean>

<bean id="currentUser" factory-bean="userProviderFactoryBean" scope="session">
    <aop:scoped-proxy/>
</bean>

You just need this:

<bean id="currentUser" class="com.xxxxx.UserProvider" scope="session">
    <aop:scoped-proxy/>
    <property name="userDao" ref="userDao"/>
</bean>

Here, UserProvider is a FactoryBean, and Spring knows how to handle that. The end result will be that the currentUser bean will be whatever UserProvider generates, rather than an instance of UserProvider itself.

The factory-bean attribute is used when the factory is not a FactoryBean implementation, but just a POJO, and it allows you to tell Spring explicitly how to use the factory. But because you're using FactoryBean, there's no need for this attribute.