AspectJ および Spring Data MongoDb で Spring AOP を使用しており、オブジェクトの永続化に問題が発生しています。
この場合、AclEntryImpl を公開する AclEntryDaoImpl があります。AclEntryImpl に標準 Java オブジェクト (「非 Spring」Bean) であるプリンシパルが提供されている場合、mongoTemplate.save() は期待どおりに機能します。ただし、プリンシパルが Spring Bean の場合、Mongo はオブジェクトを変換できず、 MappingException が発生しorg.springframework.data.mapping.model.MappingException: No id property found on class class com.sun.proxy.$Proxy33
ます。(a) オブジェクトを分離したままにし、(b) AOP (LoggingAspect) を呼び出すには、すべてのオブジェクトを Spring Bean にする必要があります。
最後に、Mongo はターゲット オブジェクトAclEntryImpl
をプロキシとして認識し、呼び出されないcom.sun.proxy.$Proxy33
ため、Spring コンバーターを利用できません。Converter<Principal, DBObject>
どんな助けでも大歓迎です!
切れ端:
私のSpring XML構成は次のとおりです。
<beans>
<context:component-scan base-package="a.b" />
<context:property-placeholder location="config.properties" />
<aop:aspectj-autoproxy />
<bean id="loggingAspect" class="a.b.LoggingAspect" />
<mongo:db-factory host="${database.host}" port="${database.port}" dbname="${database.dbname}" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="aclEntryDao" class="a.b.AclEntryDaoImpl">
<lookup-method name="createAclEntry" bean="aclEntry" />
</bean>
</beans>
AclEntryImpl:
@Document
@Component
@Scope("prototype")
public class AclEntryImpl implements AclEntry {
@Id
private String id;
private String service;
@DBRef @Expose
private Principal principal;
@Expose
private boolean accessGranted;
@Expose
private List<Permission> permissions;
@Override @Loggable @MongoSaveReturned
public AclEntry save() {
return this;
}
...getters and setters...
}
AclEntryDaoImpl:
@Repository
public abstract class AclEntryDaoImpl implements AclEntryDao {
@Override @Loggable
public AclEntry addEntry(String serviceName, Principal principal, Permission[] permissions, boolean accessGranted) throws Exception {
AclEntry entry = createAclEntry(); //<-- Spring lookup-method
entry.setService(serviceName);
entry.setPrincipal(principal); //<-- com.sun.proxy.$Proxy33
entry.setAccessGranted(accessGranted);
for (Permission permission : permissions) {
if (!entry.addPermission(permission)) {
return null;
}
}
return entry.save();
}
... other DAO methods ...
}
ロギングアスペクト:
@Aspect
public class LoggingAspect {
@Autowired
private MongoTemplate mongoTemplate;
@Pointcut("execution(!void a.b..*.*(..))")
public void returningMethods() {}
@AfterReturning(pointcut="returningMethods() && @annotation(MongoSaveReturned)", returning="retVal")
public Object mongoSaveReturnedAdvice(Object retVal) {
Logger logger = null;
try {
logger = getLogger(retVal);
mongoTemplate.save(retVal); //<-- throws MappingException
log(logger, "save: " + retVal.toString());
} catch (Exception e) {
log(logger, "throw: " + e.toString());
}
return retVal;
}
... other logging methods ...
}