2011-03-20 2 views
1

클래스의 @Aspect 주석을 사용하여 pointcut을 정의했습니다. 내 포인트 컷에 buildDao에 대한 참조가있는 경우 JPA entityManager가 Pointcut에서 null입니다.

<aop:aspectj-autoproxy proxy-target-class="true"/> 
<!-- Messaging pointcut --> 
<bean id="messagePointcut" class="com.adobe.codex.aspects.MessagePointcut" > 
    <constructor-arg ref="msgPointcutEntityFactory"/> 
    <property name="buildDao" ref="buildDao"/> 
</bean> 


<!-- enable our own annotation --> 
<aop:config proxy-target-class="true"> 
    <aop:aspect ref="messagePointcut"> 
     <aop:pointcut id="proxiedMethods" expression="@annotation(com..codex.aspects.annotation.MessageGateway)"/> 
     <aop:around pointcut-ref="proxiedMethods" method="interceptAnnotatedMethod"/> 
    </aop:aspect> 
</aop:config> 

불행하게도 buildDao 내부 EntityManager를 항상 널 :

나는 내 상황에서 정의한 사용자 정의 주석을 사용하여 포인트 컷을 구성합니다.

이 문제를 해결하는 가장 좋은 방법은 무엇인지 잘 모릅니다.

나는 위빙 (로드 시간)이 entityManagerFactory 빈에서 entityManager를 작성하는 방법을 모른다는 것이 문제라고 가정합니다.

여기에 내 DAO 컨텍스트 스 니펫이 있습니다.

@Aspect @Transactional() 공용 클래스 MessagePointcut가 발주 구현 MsgObservable {

private MsgPointcutEntityFactory msgEntityFactory; 
private BuildDao buildDao; 


public void setBuildDao(BuildDao buildDao) { 
    this.buildDao = buildDao; 
} 



public MessagePointcut(MsgPointcutEntityFactory msgEntityFactory){ 
    this.msgEntityFactory = msgEntityFactory; 
} 

@Transactional(readOnly = true) 
public Object interceptAnnotatedMethod(ProceedingJoinPoint pjp) { 
    Object returnedEntity = null; 
    Object originalEntity = null; 



    try { //  

     // do stuff before executing the call 
     originalEntity = msgEntityFactory.fetch(id, Build.class); 

     //execute the call 
     returnedEntity = pjp.proceed(); 

     // do stuff after executing the call 
     // ... 

    } catch (Throwable e) { 
     e.printStackTrace(); 
    } 
    return returnedEntity; 
} 

@Override 
public int getOrder() { 
    return 2; 
} 

}

그리고 내 DAO의 미리보기 : 여기

<context:annotation-config /> 
<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaProperties"> 
     <util:properties 
      location="classpath:com//codex/dao/jpa/hibernate.properties" /> 
    </property> 
</bean> 

<bean id="buildDao" class="com..codex.dao.jpa.JpaBuildDao"> 
    <description> 
     A DAO for Builds. 
    </description> 
    <property name="queryHelper" ref="queryHelper" /> 
    <property name="partDao" ref="partDao" /> 
    <property name="buildQueryFactory" ref="buildQueryFactory" /> 

</bean>  

내 포인트 컷이다

@ 보관실 개 공용 클래스 JpaBuildDao는 BuildDao가 {

private static final Log log = LogFactory.getLog(JpaBuildDao.class); 

@PersistenceContext 
private EntityManager entityManager; 

private QueryHelper queryHelper; 
private BuildQueryFactory standardQueryFactory; 
private PartDao partDao; 

public Build getFlatBuild(Integer id) { 
    Build returnBuild; 

     Query query = entityManager.createQuery(
       "SELECT b FROM Build b " + 
       "WHERE " + 
       "b.id = :id"); 
     query.setParameter("id", id); 
     returnBuild = (Build) query.getSingleResult(); 


    return returnBuild; 
} 

답변

1

일부 진전을 구현합니다. 진짜 문제는 buildDao가 entityManager를 인스턴스화하는 필수 Jpa 프록시가없는 pointcut에 raw로 주입된다는 것입니다.

다른 구성 세부 정보가 혼합되었을 때만 문제가 발생합니다. 나는 또한 내 포인트 컷에 콩을 주입이 개 MethodInvokingFactoryBeans와 인스턴스가 : 나는이 두 콩을 제거하면

<bean id="registerListenerJms" 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="targetObject"> 
     <ref local="messagePointcut" /> 
    </property> 
    <property name="targetMethod"> 
     <value>registerObserver</value> 
    </property> 
    <property name="arguments"> 
     <list> 
      <ref bean="jmsGateway" /> 
     </list> 
    </property> 
</bean> 

<bean id="registerListenerAmf" 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="targetObject"> 
     <ref local="messagePointcut" /> 
    </property> 
    <property name="targetMethod"> 
     <value>registerObserver</value> 
    </property> 
    <property name="arguments"> 
     <list> 
      <ref bean="amfGateway" /> 
     </list> 
    </property> 
</bean> 

내 포인트 컷은 원시 프록시를 얻을하지 않습니다,하지만 DAO에 대한 참조와 JdkDynamicAopProxy을 가져옵니다.

MethodInvokingFactoryBean이 dao를 주입하는 것을 망쳐 놓은 이유를 모르겠지만 그렇습니다.

결론은 시간을 내 관찰자 패턴을 구현에 후크 할 콩 포인트 컷의 종속성과 함께 살고있는 MethodInvokingFactoryBeans와 제거 해요 인을위한 것입니다.

아니 완벽한 솔루션 만 허용 해결 방법.