JPA 实体管理器在切入点中为空
我在类中使用 @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 @事务性() public class MessagePointcut Implements 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;
}
}
的片段
以及我的 dao @Repository 公共类 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;
}
I have defined a pointcut using the @Aspect annotation in my class.
I configure the pointcut using a custom annotation which I have defined in my context:
<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>
Unfortunately the entityManager inside buildDao is always null if I have a reference to buildDao in my pointcut.
Not sure what the best way to fix this would be.
I'm assuming the problem is that the weaving used (load time) is does not know how to create an entityManager from the entityManagerFactory bean.
here is a snippet of my dao context.
<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>
Here is my Pointcut:
@Aspect
@Transactional()
public class MessagePointcut implements 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;
}
}
And a snippet of my dao
@Repository
public class JpaBuildDao implements 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
取得了一些进展。真正的问题是 buildDao 被原始注入到切入点中,没有实例化实体管理器所需的 Jpa 代理。
事实证明,只有当另一个配置细节混入其中时,才会出现此问题。我还有两个 MethodInvokingFactoryBean 实例,将 bean 注入到我的切入点中:
当我删除这两个 bean 时,我的切入点不会获得原始代理,但它会获得一个带有对 dao 引用的 JdkDynamicAopProxy。
不知道为什么 MethodInvokingFactoryBean 会搞乱注入 dao,但确实如此。
最重要的是,我暂时删除了 MethodInvokingFactoryBean,它实现了我的观察者模式,并依赖于要挂接的 bean 上的切入点。
这不是一个完整的解决方案,而是一个可接受的解决方法。
Made some progress. The real issue is that buildDao is injected raw into the pointcut w/o the required Jpa proxy that instantiates the entityManager.
Turns out the issue only occurs when another config detail comes into the mix. I also have two MethodInvokingFactoryBean instances injecting beans into my pointcut:
When I remove these two beans my pointcut doesn't get the raw proxy, but it gets a JdkDynamicAopProxy with a reference to the dao.
Have no clue why MethodInvokingFactoryBean messes up injecting the dao, but it does.
Bottom line is for the time being I'm removing the MethodInvokingFactoryBean that implement my observer pattern and live with a dependency of the pointcut on the beans that want to hook in.
Not a complete solution but an acceptable workaround.