首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何创建扩展AuditingEntityListener的自定义审计实体侦听器

如何创建扩展AuditingEntityListener的自定义审计实体侦听器
EN

Stack Overflow用户
提问于 2021-07-15 12:29:34
回答 1查看 2.6K关注 0票数 2

我已经通过Sping Data实现了审计,但现在我希望能够控制更新并使用自定义逻辑创建时间戳。因此,我想编写一个自定义审计实体监听器,它扩展了Auditingentitylistener。

我有以下泛型实体类,在其中注册自定义审核实体侦听器:

代码语言:javascript
运行
复制
@MappedSuperclass
@Audited
@EntityListeners(CustomAuditingEntityListener.class)
public class AuditableEntity extends BaseEntity {

    @CreatedDate
    @Column(name = "created", nullable = false)
    private Date created;

    @CreatedBy
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "created_by_id", foreignKey = @ForeignKey(name = "fk_entity_created_by_id"))
    private Account createdBy;

    @LastModifiedDate
    @Column(name = "last_updated", nullable = false)
    private Date lastUpdated;

    @LastModifiedBy
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "last_updated_by_id", foreignKey = @ForeignKey(name = "fk_entity_last_updated_by_id"))
    private Account lastUpdatedBy;

    protected AuditableEntity() {
    }

    ...

}

CustomAuditingEntityListener类定义为

代码语言:javascript
运行
复制
@Configurable
public class CustomAuditingEntityListener extends AuditingEntityListener {

    public CustomAuditingEntityListener() {
        super();
    }

    @Override
    @PrePersist
    public void touchForCreate(Object target) {
        if (//custom logic) {
            super.touchForCreate(target);
        }
    }

    @Override
    @PreUpdate
    public void touchForUpdate(Object target) {
        if (//custom logic) {
            super.touchForUpdate(target);
        }
    }

}

自定义审计实体侦听器被正确调用,但是当调用super.touchForCreate(target)super.touchForUpdate(target)时,由于AuditingEntityListener类中的处理程序为null,所以没有设置时间戳。

这是AuditingEntityListener类的代码:

代码语言:javascript
运行
复制
package org.springframework.data.jpa.domain.support;

@Configurable
public class AuditingEntityListener implements ConfigurableObject {
    private ObjectFactory<AuditingHandler> handler;

    public AuditingEntityListener() {
        JoinPoint var2 = Factory.makeJP(ajc$tjp_1, this, this);
        JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
        if (this != null && this.getClass().isAnnotationPresent(Configurable.class) && AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$before$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$1$e854fa65(this);
        }

        if ((this == null || !this.getClass().isAnnotationPresent(Configurable.class) || !AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) && this != null && this.getClass().isAnnotationPresent(Configurable.class) && AbstractDependencyInjectionAspect.ajc$if$6f1(var1)) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
        }

        if (!AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class)) && AbstractDependencyInjectionAspect.ajc$if$6f1(var2)) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
        }

    }

    public void setAuditingHandler(ObjectFactory<AuditingHandler> auditingHandler) {
        Assert.notNull(auditingHandler, "AuditingHandler must not be null!");
        this.handler = auditingHandler;
    }

    @PrePersist
    public void touchForCreate(Object target) {
        if (this.handler != null) {
            ((AuditingHandler)this.handler.getObject()).markCreated(target);
        }

    }

    @PreUpdate
    public void touchForUpdate(Object target) {
        if (this.handler != null) {
            ((AuditingHandler)this.handler.getObject()).markModified(target);
        }

    }

    static {
        ajc$preClinit();
    }
}

有人能解释我如何确保AuditingHandler不是null,并且设置得像默认的AuditingEntityListener类一样吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-19 20:52:27

使用Spring5.1,有一种非常简单的方法可以在自定义实体侦听器中自动创建Spring组件,这样就可以使用AuditingHandler

1.将客户实体侦听器声明为Spring组件。使用构造函数注入。

代码语言:javascript
运行
复制
@Component
public class CustomAuditingEntityListener {

    private ObjectFactory<AuditingHandler> handler; 
    
    public CustomAuditingEntityListener(ObjectFactory<AuditingHandler> auditingHandler) {
        this.handler = auditingHandler;
    }

    @Override
    @PrePersist
    public void touchForCreate(Object target) {
        if (//custom logic) {
            AuditingHandler object = handler.getObject();
            if (object != null) {
                object.markCreated(target);
            }

        }
    }

    @Override
    @PreUpdate
    public void touchForUpdate(Object target) {
        if (//custom logic) {
            AuditingHandler object = handler.getObject();
            if (object != null) {
                object.markModified(target);
            }
        }
    }

}

2.通过设置适当的配置属性告诉Hibernate使用Spring:

代码语言:javascript
运行
复制
@Configuration
public class JpaConfig extends JpaBaseConfiguration {
    
    @Autowired
    private ConfigurableListableBeanFactory beanFactory;

    protected JpaConfig(DataSource dataSource, JpaProperties properties,
            ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
        super(dataSource, properties, jtaTransactionManager);
    }

    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Override
    protected Map<String, Object> getVendorProperties() {
        Map<String, Object> properties = new HashMap<>();

        // This is the important line
        properties.put(org.hibernate.cfg.AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));

        return properties;
    }
}

--编辑--变体2.或者可以这样配置SpringBeanContainer,这样做的好处是不会丢失Spring填充的Hibernate属性:

代码语言:javascript
运行
复制
@Configuration
public class JpaConfig {

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
            EntityManagerFactoryBuilder builder, ConfigurableListableBeanFactory beanFactory) {

        return builder.dataSource(dataSource) //
                .packages(BaseEntity.class) //
                .persistenceUnit("myunit") //
                .properties(Map.of(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory))) //
                .build();
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68393867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档