2013-05-10 3 views
4

В моем приложении Spring у меня есть целая куча фасоли (в данном случае DAO), которые создаются как простые <bean> s в моей конфигурации XML. В этих методах представлены различные аннотации, в том числе конкретно @Transactional. Я, естественно, тоже <tx:annotation-driven />.Как получить Spring для создания AOP-прокси для моих бобов

Но для некоторых из этих объектов, хотя только некоторые из них - никаких прокси-серверов не созданы (я подтвердил это, включив ведение журнала отладки), и аннотация @Transactional не имеет никакого эффекта. Вместо этого объекты, которые содержат (обычно автоматически) ссылки на эти DAO, получают проводную ссылку на прямой класс, а не на прокси.

Все классы имеют соответствующие интерфейсы, а ссылки с помощью автоподключения всегда проходят через эти интерфейсы.

Я не могу понять, какие классы получают прокси, а какие нет. Я хочу их всех. Поэтому мой вопрос:

a) При каких обстоятельствах 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

аннотировать класс 'UserDaoImpl' с' @ Repository' который является тип '@ Component' и удалить' userDao' боб, который я предполагаю, также реализует 'UserDao' (вы получите столкновение вас раньше). И не забывайте '<компонент-сканирование>' на этом пакете. –

+0

Не повезло. Прокси создается, но аннотации все еще не вступают в силу; ни '@ Transactional', ни' @ Cacheable'. – Dan

+0

Если был создан прокси-сервер, то был обнаружен @Transactional. Что говорит вам, что транзакций не происходит? –

ответ

2

В конце концов я понял, что он терпел неудачу из-за какой-то цепи зависимостей, начиная с bean-компонента, который каким-то образом загружается «слишком рано» - в моем случае - Spring Security PermissionEvaluator. У меня все еще нет SSCCE, но я добавляю этот ответ здесь, если у кого-то была аналогичная проблема.

Решение заключалось в использовании очень позднего связывания.Я сделал свой PermssionEvaluator в ApplicationContextAware, а затем написал приватный метод для загрузки локальных ссылок с ApplicationContext, и этот метод вызывается только тогда, когда он нужен, но не во время инициализации.

Другими словами, у меня был боб, как

private AuthorizationServices authServices; 

, а затем в моей основной метод что-то вроде

if (authServices == null) 
    initBeans(); 

, а затем

private void initBeans() { 
    authServices = ac.getBean(AuthorizationServices.class); 
} 
+0

это действительно полезно! – lovespring

+0

Весна должна дать некоторую информацию или интерфейс, когда мы действительно можем получить прокси, или весна должна показать некоторую информацию, порядок того, как bean-компоненты будут init – lovespring

+0

, вы могли бы просто использовать аннотацию @Lazy для того, чтобы сделать то же самое. –

3

Аннотации @Component расскажут Spring, чтобы создать и обработать фасоль этого класса. Вам нужно, чтобы ваше приложение (или другое) сканировало этот пакет класса с помощью элемента <component-scan>.

@Service, @Repository, @Controller произведение как раз как @Component.

Что касается проксирования, Spring не проксирует все, только экземпляры классов, для которых необходимо добавить поведение. Например, с @Transactional, ему необходимо добавить поведение транзакции begin/commit/rollback. Для этого он сводит методы класса с помощью собственного кода, поэтому ему необходимо прокси. Для класса @Controller нет необходимости добавлять какие-либо действия, поэтому он просто создаст экземпляр класса.

+0

Итак, как он узнает, какие классы для прокси в отсутствие '@ Component'? Как я уже сказал, классы, с которыми я это вижу, имеют '@ Transactional' некоторые из своих методов. – Dan

+0

В отсутствие '@ Component', Spring ничего не делает с этим классом. –

+0

Кроме того, мне действительно нужно '', когда я определяю beans явно используя ''? – Dan

0

Мы столкнулись с такой же вопрос и понял, что компонент был инициализирован до org.springframework.cache.ehcache.EhCacheCacheManager в приложении , поэтому @Cacheable не работал.

Мы закончили перемещение конфигурации кеша в xml из класса конфигурации java, который принудительно (не уверен, как), инициализацию 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"/> 
Смежные вопросы