4

在我的 Spring 应用程序中,我有一大堆 bean(在本例中是 DAO),它们<bean>在我的 XML 配置中创建为 simple s。在这些方法中有各种注释,包括具体@Transactional的 . 我自然也有<tx:annotation-driven />

但是对于其中一些对象 - 尽管只有其中一些 - 没有创建代理(我通过启用调试日志记录确认了这一点)并且@Transactional注释无效。相反,包含对这些 DAO 的引用(通常是自动连接的)的对象被连接到直接类的引用,而不是代理。

所有的类都有对应的接口,自动装配的引用总是通过这些接口。

我不知道哪些类得到了代理,哪些没有。我希望他们都这样做。所以我的问题是:

a) 在什么情况下 Spring 不会为一个类创建代理,即使它实现了一些接口?

b)如何强制 Spring 创建我需要的代理?

请注意,我没有做任何事情来明确启用代理,但我过去不需要这样做。它通常只是工作。

尝试使用 Spring 3.1.3 和 3.2.2。

我没有这方面的 SSCCE。基本上我的 XML 是

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"       
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sec="http://www.springframework.org/schema/security"    
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"                       
       xmlns:cache="http://www.springframework.org/schema/cache"       
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
       http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
       http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd
       http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
">

       <bean id="userDao" class="com.soschat.dao.spring.SpringUserDAO"/>

           <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="transactionManager" class=" org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
        <property name="globalRollbackOnParticipationFailure" value="false" />
    </bean>

... etc ...
</beans>

我的代码或多或少

public class UserDaoImpl implements UserDao {

   @Override
   @Transactional
   @Cacheable
   public User getUserById(long userId) {
         // do stuff
   }
}

不知道在没有过多细节的情况下我还需要添加多少。

一个有趣的补充——我可以强制它使用 BeanNameAutoProxyCreator 创建代理。但是我放在那里的注释都没有真正生效。

4

3 回答 3

4

注释将@Component告诉 Spring 创建和处理该类的 bean。您需要让您的应用程序(或其他)上下文使用该<component-scan>元素扫描该类的包。

@Service, @Repository,@Controller工作就像@Component

至于代理,Spring 并不代理一切,只代理它需要添加行为的类的实例。例如,使用@Transactional,它需要添加开始/提交/回滚事务行为。为此,它使用自己的代码包装您的类的方法,因此它需要代理。对于一个@Controller类,它不需要添加任何行为,所以它会简单地实例化你的类。

于 2013-05-10T20:01:17.553 回答
2

最终我发现它失败了,因为某种依赖链以某种方式“过早”加载的 bean 开始——在我的例子中是 Spring Security PermissionEvaluator。我仍然没有 SSCCE,但我在此处添加此答案以防其他人遇到类似问题。

解决方案是使用非常晚的绑定。我把我的PermssionEvaluator变成了ApplicationContextAware,然后写了一个私有方法来加载本地的被引用ApplicationContext,并且这个方法只在第一次需要时调用,而不是在初始化期间。

换句话说,我有一个像

private AuthorizationServices authServices;

然后在我的主要方法中

if (authServices == null)
   initBeans();

接着

private void initBeans() {
    authServices = ac.getBean(AuthorizationServices.class);
}
于 2013-06-13T18:54:11.867 回答
0

我们遇到了同样的问题,并意识到 bean 在应用程序启动时在 org.springframework.cache.ehcache.EhCacheCacheManager 之前初始化,因此 @Cacheable 不起作用。

我们最终将缓存配置从 java 配置类移动到 xml,这强制(不确定如何)在任何应用程序 bean 之前进行 EHCacheManager 初始化。我们的应用程序中有 xml 和 java 配置。

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="classpath:ehcache.xml" p:shared="true"/>
于 2015-08-26T21:56:54.897 回答