在我的Spring应用程序中,我有一大堆bean(在这种情况下是DAO),在我的XML配置中创建为简单的<bean>
。在这些方法中有各种注释,具体包括@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创建代理。但是我放在那里的注释都没有实际生效。
答案 0 :(得分:3)
@Component
注释将告诉Spring创建和处理该类的bean。您需要让您的应用程序(或其他)上下文扫描具有<component-scan>
元素的类包。
@Service
,@Repository
,@Controller
就像@Component
一样工作。
至于代理,Spring不会代理所有内容,只需要添加行为所需的类的实例。例如,对于@Transactional
,它需要添加begin / commit / rollback事务行为。为此,它使用自己的代码包装类的方法,因此需要代理。对于@Controller
类,它不需要添加任何行为,因此它只是实例化您的类。
答案 1 :(得分:2)
最终我发现它失败了,因为某种依赖链从一个以某种方式“太早”加载的bean开始 - 在我的例子中是一个Spring Security PermissionEvaluator
。我仍然没有SSCCE,但我在这里添加这个答案以防其他人遇到类似的问题。
解决方案是使用非常晚的绑定。我将PermssionEvaluator
转换为ApplicationContextAware
,然后编写了一个私有方法来加载来自ApplicationContext
的本地引用,并且只在首次需要时调用此方法,而不是在初始化。
换句话说,我有一个类似
的豆子private AuthorizationServices authServices;
然后在我的主要方法中像
if (authServices == null)
initBeans();
然后
private void initBeans() {
authServices = ac.getBean(AuthorizationServices.class);
}
答案 2 :(得分:0)
我们遇到了同样的问题,并意识到在应用程序启动时org.springframework.cache.ehcache.EhCacheCacheManager之前初始化了bean,因此@Cacheable无效。
我们最终将缓存配置从java配置类移动到xml,强制(不确定如何),EHCacheManager在任何应用程序bean之前初始化。我们的应用程序中有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"/>