1

クラスで @Aspect アノテーションを使用してポイントカットを定義しました。

コンテキストで定義したカスタム注釈を使用してポイントカットを構成します。

<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 への参照がある場合、buildDao 内の entityManager は常に null です。

これを修正する最善の方法が何であるかはわかりません。

問題は、使用されるウィービング (ロード時間) が entityManagerFactory Bean から entityManager を作成する方法を知らないことだと思います。

ここに私の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>    

ここに私のポイントカットがあります:

@Aspect @Transactional() public class MessagePointcut は Ordered、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;
}

}

そして、私のダオのスニペット

@Repository public class 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;
}
4

1 に答える 1

1

ある程度の進歩を遂げました。本当の問題は、buildDaoがentityManagerをインスタンス化する必要なJpaプロキシなしでポイントカットに生で注入されることです。

この問題は、別の構成の詳細が混在している場合にのみ発生することが判明しました。また、ポイントカットにBeanを挿入する2つのMethodInvokingFactoryBeanインスタンスがあります。

<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> 

これらの2つのBeanを削除すると、ポイントカットは生のプロキシを取得しませんが、daoへの参照を含むJdkDynamicAopProxyを取得します。

MethodInvokingFactoryBeanがdaoの注入を台無しにする理由はわかりませんが、そうです。

結論としては、当面の間、オブザーバーパターンを実装し、フックするBeanへのポイントカットの依存関係を維持するMethodInvokingFactoryBeanを削除します。

完全な解決策ではありませんが、許容できる回避策です。

于 2011-03-23T19:56:14.963 に答える