我正在使用带有AspectJ和Spring Data MongoDb的Spring AOP,并且在持久化对象时遇到了麻烦。
在这种情况下,我有一个公开AclEntryImpl的AclEntryDaoImpl。当为AclEntryImpl提供作为标准Java对象的Principal(“非Spring”bean)时,mongoTemplate.save()按预期工作。但是,当Principal是Spring bean时,Mongo无法转换对象并导致MappingException org.springframework.data.mapping.model.MappingException: No id property found on class class com.sun.proxy.$Proxy33
。我的所有对象都需要是Spring bean,以便(a)我保持我的对象解耦,并且(b)调用我的AOP(LoggingAspect)。
最后,我无法利用Spring转换器,因为Mongo将目标对象AclEntryImpl
视为代理com.sun.proxy.$Proxy33
,因此永远不会调用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 ...
}
LoggingAspect:
@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 ...
}