2

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

}
4

0 に答える 0