【源码】Spring Data JPA原理解析之Auditing执行原理

Spring Data JPA系列

1、SpringBoot集成JPA及基本使用

2、Spring Data JPA Criteria查询、部分字段查询

3、Spring Data JPA数据批量插入、批量更新真的用对了吗

4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作

5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用

6、【源码】Spring Data JPA原理解析之Repository的自动注入(一)

7、【源码】Spring Data JPA原理解析之Repository的自动注入(二)

8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码

9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)

10、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)

11、【源码】Spring Data JPA原理解析之Repository自定义方法添加@Query注解的执行原理

12、【源码】SpringBoot事务注册原理

13、【源码】Spring Data JPA原理解析之事务注册原理

14、【源码】Spring Data JPA原理解析之事务执行原理

15、【源码】SpringBoot编程式事务使用及执行原理

16、【源码】Spring事务之传播特性的详解

17、【源码】Spring事务之事务失效及原理

18、【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理

19、【源码】Spring Data JPA原理解析之Auditing执行原理

前言

Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用-CSDN博客这篇博文中,跟大家分享了JPA中的Auditing审计功能。JPA通过注解的方式,提供了对数据库表中的数据记录自动添加操作人及操作时间,以及自定义监听器,实现实体插入、编辑、删除的监听,添加日志等。

Auditing使用回顾

2.1 在启动类中添加@EnableJpaAuditing注解,开启Auditing;

2.2 在实体类中添加监听器及操作人、操作时间的注解,代码如下:

java 复制代码
package com.jingai.jpa.dao.entity;

@Data
@Entity
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
// 添加AuditingEntityListener实体监听
@EntityListeners(AuditingEntityListener.class)
@Table(name = "tb_user")
public class UserEntity {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
 
    private String name;
    private String state;
 
    // 添加审计的注解
    @CreatedBy
    private Long createBy;
    @CreatedDate
    private Date createTime;
    @LastModifiedBy
    private Long modifyBy;
    @LastModifiedDate
    private Date modifyTime;
 
}

2.3 自定义AuditorAware,重写getCurrentAuditor(),返回审计员主键,实现数据记录的创建人、操作人的自动填充;

通过以上三步,即可实现tb_user表中的createBy、createTime、modifyBy、modifyTime四个字段数据的自动填充。详见:

Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用-CSDN博客

Auditing的执行原理

Auditing审计功能提供了对数据库表中的数据记录自动添加操作人及操作时间,其核心实现在AuditingEntityListener。

3.1 AuditingEntityListener

AuditingEntityListener的源码如下:

java 复制代码
package org.springframework.data.jpa.domain.support;

@Configurable
public class AuditingEntityListener {

	// AuditingHandler处理器
	private @Nullable ObjectFactory<AuditingHandler> handler;

	public void setAuditingHandler(ObjectFactory<AuditingHandler> auditingHandler) {

		Assert.notNull(auditingHandler, "AuditingHandler must not be null");
		this.handler = auditingHandler;
	}

	/**
	 * 用于设置目标对象的修改和创建日期以及审核程序。该方法添加了@PrePersist注解,在新增时回调
	 */
	@PrePersist
	public void touchForCreate(Object target) {

		Assert.notNull(target, "Entity must not be null");

		if (handler != null) {
			// 获取AuditingHandler的真实对象
			AuditingHandler object = handler.getObject();
			if (object != null) {
				// 标记新创建
				object.markCreated(target);
			}
		}
	}

	/**
	 * 用于设置目标对象的修改和创建日期以及审核程序,方法添加了@PreUpdate注解
	 */
	@PreUpdate
	public void touchForUpdate(Object target) {

		Assert.notNull(target, "Entity must not be null");

		if (handler != null) {
			// 获取AuditingHandler的真实对象
			AuditingHandler object = handler.getObject();
			if (object != null) {
				// 标记被修改
				object.markModified(target);
			}
		}
	}
}

在AuditingEntityListener中,定义了两个方法,分别添加了@PrePersist和@PerUpdate,标记在新增和修改前回调。即AuditingEntityListener也是使用的Hibernate中的EventListener的监听回调注解。详见:

【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理-CSDN博客

通过上面的博文可知,当执行persist()时,会先执行添加@PrePersist注解的监听器方法,即Auditing中的AuditingEntityListener的touchForCreate()方法会被回调。该方法会判断handler是否为空,如果不为空,则执行handler的markCreated()方法。所以核心实现在handler,而该handler是AuditingHandler对象。

在Auditing的使用中,其中一步是需要添加@EnableJpaAuditing注解,开启Auditing。该注解的作用就在于为AuditingEntityListener的handler赋值。

3.2 EnableJpaAuditing注解

EnableJpaAuditing注解的源码如下:

java 复制代码
package org.springframework.data.jpa.repository.config;

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
// 自动引入JpaAuditingRegistrar
@Import(JpaAuditingRegistrar.class)
public @interface EnableJpaAuditing {

}

该注解会自动引入JpaAuditingRegistrar。

3.3 JpaAuditingRegistrar

JpaAuditingRegistrar的相关代码如下:

java 复制代码
package org.springframework.data.jpa.repository.config;

class JpaAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {

	private static final String BEAN_CONFIGURER_ASPECT_CLASS_NAME = "org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";

	@Override
	protected Class<? extends Annotation> getAnnotation() {
		return EnableJpaAuditing.class;
	}

	@Override
	protected String getAuditingHandlerBeanName() {
		return "jpaAuditingHandler";
	}

	@Override
	public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {

		Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null");
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		// 注册AnnotationBeanConfigurerAspect
		registerBeanConfigurerAspectIfNecessary(registry);
		// 注册审计处理的bean,AuditingHandler
		super.registerBeanDefinitions(annotationMetadata, registry);
		// 注册AuditingBeanFactoryPostProcessor后置处理器
		registerInfrastructureBeanWithId(
				BeanDefinitionBuilder.rootBeanDefinition(AuditingBeanFactoryPostProcessor.class).getRawBeanDefinition(),
				AuditingBeanFactoryPostProcessor.class.getName(), registry);
	}

	/**
	 * 注册AuditingEntityListener监听器
	 */
	@Override
	protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
			BeanDefinitionRegistry registry) {
		// 如果不存在JpaMetamodelMappingContext,注册JpaMetamodelMappingContextFactoryBean
		// MappingContext用来映射实体与数据库之间关系的机制
		if (!registry.containsBeanDefinition(JPA_MAPPING_CONTEXT_BEAN_NAME)) {
			registry.registerBeanDefinition(JPA_MAPPING_CONTEXT_BEAN_NAME, //
					new RootBeanDefinition(JpaMetamodelMappingContextFactoryBean.class));
		}
		// 创建AuditingEntityListener监听器的bean
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(AuditingEntityListener.class);
		// 设置AuditingEntityListener的auditingHandler属性,值为jpaAuditingHandler对象
		builder.addPropertyValue("auditingHandler",
				ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), null));
		// 注册AuditingEntityListener
		registerInfrastructureBeanWithId(builder.getRawBeanDefinition(), AuditingEntityListener.class.getName(), registry);
	}

	// 省略其他
}

JpaAuditingRegistrar实现了ImportBeanDefinitionRegistrar,所以在Spring启动的时候,会执行registerBeanDefinitions()方法。在registerBeanDefinitions()方法中,核心是调用父类的AuditingBeanDefinitionRegistrarSupport的registerBeanDefinitions()方法。

3.4 AuditingBeanDefinitionRegistrarSupport

AuditingBeanDefinitionRegistrarSupport的源码如下:

java 复制代码
public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar {

	private static final String AUDITOR_AWARE = "auditorAware";
	private static final String DATE_TIME_PROVIDER = "dateTimeProvider";
	private static final String MODIFY_ON_CREATE = "modifyOnCreation";
	private static final String SET_DATES = "dateTimeForNow";

	/**
	 * Spring容器会自动执行ImportBeanDefinitionRegistrar.registerBeanDefinitions(),添加AnnotationAuditingConfiguration装配类
	 * @param annotationMetadata
	 * @param registry
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {

		Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null");
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		// 注册审计处理的bean,AuditingHandler
		AbstractBeanDefinition ahbd = registerAuditHandlerBeanDefinition(getConfiguration(annotationMetadata), registry);
		// 注册AuditingEntityListener监听器
		registerAuditListenerBeanDefinition(ahbd, registry);
	}

	/**
	 * 注册审计处理的bean,AuditingHandler
	 * @param configuration AnnotationAuditingConfiguration对象,记录@EnableJpaAuditing的配置信息
	 * @param registry
	 * @return
	 */
	protected AbstractBeanDefinition registerAuditHandlerBeanDefinition(AuditingConfiguration configuration,
			BeanDefinitionRegistry registry) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(configuration, "AuditingConfiguration must not be null");
		// 使用给定AuditingConfiguration中的默认属性配置AuditingHandler的BeanDefinitionBuilder
		BeanDefinitionBuilder builder = getAuditHandlerBeanDefinitionBuilder(configuration);
		postProcess(builder, configuration, registry);
		// 获取AuditingHandler的bean
		AbstractBeanDefinition ahbd = builder.getBeanDefinition();
		registry.registerBeanDefinition(getAuditingHandlerBeanName(), ahbd);
		return ahbd;
	}

	protected void postProcess(BeanDefinitionBuilder builder, AuditingConfiguration configuration,
			BeanDefinitionRegistry registry) {}


	/**
	 * 使用给定AuditingConfiguration中的默认属性配置AuditingHandler的BeanDefinitionBuilder
	 */
	protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingConfiguration configuration) {

		Assert.notNull(configuration, "AuditingConfiguration must not be null");

		return configureDefaultAuditHandlerAttributes(configuration,
				BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class));
	}

	/**
	 * 使用给定AuditingConfiguration中的默认属性配置给定的BeanDefinitionBuilder
	 */
	protected BeanDefinitionBuilder configureDefaultAuditHandlerAttributes(AuditingConfiguration configuration,
			BeanDefinitionBuilder builder) {

		if (StringUtils.hasText(configuration.getAuditorAwareRef())) {
			// 创建一个懒加载的目标资源的auditorAwareRef的BeanDefinition对象
			builder.addPropertyValue(AUDITOR_AWARE,
					createLazyInitTargetSourceBeanDefinition(configuration.getAuditorAwareRef()));
		} else {
			builder.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
		}

		// 设置AuditingHandler的父类AuditingHandlerSupport的dateTimeForNow和modifyOnCreation
		builder.addPropertyValue(SET_DATES, configuration.isSetDates());
		builder.addPropertyValue(MODIFY_ON_CREATE, configuration.isModifyOnCreate());

		// 设置AuditingHandler的父类AuditingHandlerSupport的dateTimeProvider
		if (StringUtils.hasText(configuration.getDateTimeProviderRef())) {
			builder.addPropertyReference(DATE_TIME_PROVIDER, configuration.getDateTimeProviderRef());
		} else {
			builder.addPropertyValue(DATE_TIME_PROVIDER, CurrentDateTimeProvider.INSTANCE);
		}

		builder.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);

		return builder;
	}

	/**
	 * 返回一个AnnotationAuditingConfiguration对象,记录@EnableJpaAuditing的配置信息
	 */
	protected AuditingConfiguration getConfiguration(AnnotationMetadata annotationMetadata) {
		return new AnnotationAuditingConfiguration(annotationMetadata, getAnnotation());
	}

	/**
	 * 在JpaAuditingRegistrar中返回@EnableJpaAuditing
	 * @return
	 */
	protected abstract Class<? extends Annotation> getAnnotation();

	protected abstract void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
			BeanDefinitionRegistry registry);

	protected abstract String getAuditingHandlerBeanName();

	protected void registerInfrastructureBeanWithId(AbstractBeanDefinition definition, String id,
			BeanDefinitionRegistry registry) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(id, definition);
	}

	/**
	 * 创建一个懒加载的目标资源的auditorAwareRef的BeanDefinition对象
	 */
	private BeanDefinition createLazyInitTargetSourceBeanDefinition(String auditorAwareRef) {

		BeanDefinitionBuilder targetSourceBuilder = rootBeanDefinition(LazyInitTargetSource.class);
		targetSourceBuilder.addPropertyValue("targetBeanName", auditorAwareRef);

		BeanDefinitionBuilder builder = rootBeanDefinition(ProxyFactoryBean.class);
		builder.addPropertyValue("targetSource", targetSourceBuilder.getBeanDefinition());

		return builder.getBeanDefinition();
	}
}

在registerBeanDefinitions()方法中,执行如下:

1)执行registerAuditHandlerBeanDefinition(),通过@EnableJpaAuditing注解的中配置信息,传入AuditHandler中,注册Audit的处理器AuditHandler的bean到Spring容器;

2)执行registerAuditListenerBeanDefinition(),该方法在子类JpaAuditingRegistrar中实现。该方法注册Auditing的监听器AuditingEntityListener,并将1)中的AuditHandler设置给AuditingEntityListener;

3.5 AuditHandler

AuditHandler的源码如下:

java 复制代码
package org.springframework.data.auditing;

public class AuditingHandler extends AuditingHandlerSupport implements InitializingBean {

	private static final Log logger = LogFactory.getLog(AuditingHandler.class);

	private Optional<AuditorAware<?>> auditorAware;

	public AuditingHandler(PersistentEntities entities) {

		super(entities);
		Assert.notNull(entities, "PersistentEntities must not be null");

		this.auditorAware = Optional.empty();
	}

	public static AuditingHandler from(MappingContext<?, ?> mappingContext) {
		return new AuditingHandler(PersistentEntities.of(mappingContext));
	}

	/**
	 * 在创建AuditingHandler时,设置了builder.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE),
	 * 所以会将Spring容器中的AuditorAware自动调用该方法进行设置。AuditorAware用户获取当前审计人信息
	 * @param auditorAware
	 */
	public void setAuditorAware(AuditorAware<?> auditorAware) {

		Assert.notNull(auditorAware, "AuditorAware must not be null");
		this.auditorAware = Optional.of(auditorAware);
	}

	/**
	 * 标记实体被创建
	 */
	public <T> T markCreated(T source) {

		Assert.notNull(source, "Entity must not be null");
		// 执行父类的方法
		return markCreated(getAuditor(), source);
	}

	/**
	 * 标记实体被更新
	 */
	public <T> T markModified(T source) {

		Assert.notNull(source, "Entity must not be null");
		// 执行父类的方法
		return markModified(getAuditor(), source);
	}

	/**
	 * 如果存在auditorAware,则执行auditorAware.getCurrentAuditor(),获取审计人;否则为Auditor.none()
	 */
	Auditor<?> getAuditor() {

		return auditorAware.map(AuditorAware::getCurrentAuditor).map(Auditor::ofOptional) //
				.orElse(Auditor.none());
	}

	public void afterPropertiesSet() {

		if (!auditorAware.isPresent()) {
			logger.debug("No AuditorAware set; Auditing will not be applied");
		}
	}
}

在AuditHandler中,核心实现在父类AuditingHandlerSupport。

3.6 AuditingHandlerSupport

AuditingHandlerSupport的源码如下:

java 复制代码
package org.springframework.data.auditing;

public abstract class AuditingHandlerSupport {

	private static final Log logger = LogFactory.getLog(AuditingHandlerSupport.class);

	// 审计bean的包装工厂,该类的实现为DefaultAuditableBeanWrapperFactory
	private final AuditableBeanWrapperFactory factory;

	private DateTimeProvider dateTimeProvider = CurrentDateTimeProvider.INSTANCE;
	private boolean dateTimeForNow = true;
	private boolean modifyOnCreation = true;

	public AuditingHandlerSupport(PersistentEntities entities) {

		Assert.notNull(entities, "PersistentEntities must not be null");

		this.factory = new MappingAuditableBeanWrapperFactory(entities);
	}

	public void setDateTimeForNow(boolean dateTimeForNow) {
		this.dateTimeForNow = dateTimeForNow;
	}
	public void setModifyOnCreation(boolean modifyOnCreation) {
		this.modifyOnCreation = modifyOnCreation;
	}
	public void setDateTimeProvider(@Nullable DateTimeProvider dateTimeProvider) {
		this.dateTimeProvider = dateTimeProvider == null ? CurrentDateTimeProvider.INSTANCE : dateTimeProvider;
	}

	protected final boolean isAuditable(Object source) {

		Assert.notNull(source, "Source entity must not be null");

		return factory.getBeanWrapperFor(source).isPresent();
	}
	<T> T markCreated(Auditor<?> auditor, T source) {

		Assert.notNull(source, "Source entity must not be null");

		return touch(auditor, source, true);
	}

	<T> T markModified(Auditor<?> auditor, T source) {

		Assert.notNull(source, "Source entity must not be null");

		return touch(auditor, source, false);
	}

	/**
	 * 处理
	 * @param auditor:审计人信息
	 * @param target:目标实体,即实体类
	 * @param isNew:是否新增
	 */
	private <T> T touch(Auditor<?> auditor, T target, boolean isNew) {
		// 创建实体类的包装类,用于设置审计相关的属性值,
		// 在getBeanWrapperFor()方法中,解析实体类定义的审计相关的注解的元数据,
		// 包装成DefaultAuditableBeanWrapperFactory.ReflectionAuditingBeanWrapper
		Optional<AuditableBeanWrapper<T>> wrapper = factory.getBeanWrapperFor(target);
		// 对实体解包
		return wrapper.map(it -> {
			// 设置审计人信息。@createBy、@lastModifiedBy
			touchAuditor(auditor, it, isNew);
			// 设置日期
			Optional<TemporalAccessor> now = dateTimeForNow ? touchDate(it, isNew) : Optional.empty();

			if (logger.isDebugEnabled()) {

				Object defaultedNow = now.map(Object::toString).orElse("not set");
				Object defaultedAuditor = auditor.isPresent() ? auditor.toString() : "unknown";

				logger.debug(
						LogMessage.format("Touched %s - Last modification at %s by %s", target, defaultedNow, defaultedAuditor));
			}
			// 返回设置了审计信息的对象
			return it.getBean();
		}).orElse(target);
	}

	/**
	 * 设置修改和创建审核员。仅在新的可审核对象上设置创建审核器
	 */
	private void touchAuditor(Auditor<?> auditor, AuditableBeanWrapper<?> wrapper, boolean isNew) {

		if(!auditor.isPresent()) {
			return;
		}

		Assert.notNull(wrapper, "AuditableBeanWrapper must not be null");

		// 如果是新增,修改createBy
		if (isNew) {
			wrapper.setCreatedBy(auditor.getValue());
		}
		// 如果不是新增 || 配置了modifyOnCreation为true,修改lastModifiedBy
		if (!isNew || modifyOnCreation) {
			wrapper.setLastModifiedBy(auditor.getValue());
		}
	}

	/**
	 * 设置操作时间
	 */
	private Optional<TemporalAccessor> touchDate(AuditableBeanWrapper<?> wrapper, boolean isNew) {

		Assert.notNull(wrapper, "AuditableBeanWrapper must not be null");
		// 获取当前时间
		Optional<TemporalAccessor> now = dateTimeProvider.getNow();

		Assert.notNull(now, () -> String.format("Now must not be null Returned by: %s", dateTimeProvider.getClass()));
		// 设置创建时间
		now.filter(__ -> isNew).ifPresent(wrapper::setCreatedDate);
		// 设置修改时间
		now.filter(__ -> !isNew || modifyOnCreation).ifPresent(wrapper::setLastModifiedDate);

		return now;
	}
}

在AuditingHandlerSupport中,无论是新增还是编辑,最后都会调用touch()方法,该方法主要执行如下:

1)执行factory.getBeanWrapperFor(target),获取一个AuditableBeanWrapper对象,该对象为DefaultAuditableBeanWrapperFactory.ReflectionAuditingBeanWrapper;

该方法会执行AnnotationAuditingMetadata.getMetadata(it.getClass()),解析实体类中定义的审计相关注解的元数据,存放对应的注解的Field对象,并将信息添加到ReflectionAuditingBeanWrapper中。

2)执行touchAuditor(),根据新增或修改,调用ReflectionAuditingBeanWrapper的对应审计方法,为对应审计的审计人Field赋值;

3)执行touchDate(),根据新增或修改,调用ReflectionAuditingBeanWrapper的对应审计方法,为对应审计的时间Field赋值;

4)返回包装后的实体对象;

3.7 ReflectionAuditingBeanWrapper

ReflectionAuditingBeanWrapper的代码如下:

java 复制代码
package org.springframework.data.auditing;

class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory {

	/**
	 * 保存实体类的审计相关注解的元数据
	 */
	static class ReflectionAuditingBeanWrapper<T> extends DateConvertingAuditableBeanWrapper<T> {

		private final AnnotationAuditingMetadata metadata;
		private final T target;

		/**
		 * 保存实体类的审计相关注解的元数据
		 */
		public ReflectionAuditingBeanWrapper(ConversionService conversionService, T target) {
			super(conversionService);

			Assert.notNull(target, "Target object must not be null");

			this.metadata = AnnotationAuditingMetadata.getMetadata(target.getClass());
			this.target = target;
		}

		/**
		 * 为属性Field赋值
		 */
		@Override
		public Object setCreatedBy(Object value) {
			return setField(metadata.getCreatedByField(), value);
		}

		@Override
		public TemporalAccessor setCreatedDate(TemporalAccessor value) {
			return setDateField(metadata.getCreatedDateField(), value);
		}

		@Override
		public Object setLastModifiedBy(Object value) {
			return setField(metadata.getLastModifiedByField(), value);
		}

		@Override
		public Optional<TemporalAccessor> getLastModifiedDate() {

			return getAsTemporalAccessor(metadata.getLastModifiedDateField().map(field -> {

				Object value = org.springframework.util.ReflectionUtils.getField(field, target);
				return value instanceof Optional ? ((Optional<?>) value).orElse(null) : value;

			}), TemporalAccessor.class);
		}

		@Override
		public TemporalAccessor setLastModifiedDate(TemporalAccessor value) {
			return setDateField(metadata.getLastModifiedDateField(), value);
		}

		@Override
		public T getBean() {
			return target;
		}

		private <S> S setField(Optional<Field> field, S value) {

			field.ifPresent(it -> ReflectionUtils.setField(it, target, value));

			return value;
		}

		private TemporalAccessor setDateField(Optional<Field> field, TemporalAccessor value) {

			field.ifPresent(it -> ReflectionUtils.setField(it, target, getDateValueToSet(value, it.getType(), it)));

			return value;
		}
	}
}

ReflectionAuditingBeanWrapper提供了setField的方法,为对应的审计字段赋值。

3.7 AnnotationAuditingMetadata

AnnotationAuditingMetadata的源码如下:

java 复制代码
package org.springframework.data.auditing;

final class AnnotationAuditingMetadata {

	// 定义注解属性过滤器
	private static final AnnotationFieldFilter CREATED_BY_FILTER = new AnnotationFieldFilter(CreatedBy.class);
	private static final AnnotationFieldFilter CREATED_DATE_FILTER = new AnnotationFieldFilter(CreatedDate.class);
	private static final AnnotationFieldFilter LAST_MODIFIED_BY_FILTER = new AnnotationFieldFilter(LastModifiedBy.class);
	private static final AnnotationFieldFilter LAST_MODIFIED_DATE_FILTER = new AnnotationFieldFilter(
			LastModifiedDate.class);

	private static final Map<Class<?>, AnnotationAuditingMetadata> metadataCache = new ConcurrentHashMap<>();

	private final Optional<Field> createdByField;
	private final Optional<Field> createdDateField;
	private final Optional<Field> lastModifiedByField;
	private final Optional<Field> lastModifiedDateField;

	/**
	 * Creates a new {@link AnnotationAuditingMetadata} instance for the given type.
	 *
	 * @param type must not be {@literal null}.
	 */
	private AnnotationAuditingMetadata(Class<?> type) {

		Assert.notNull(type, "Given type must not be null");
		// 解析审计的注解,获取对应属性Field对象
		this.createdByField = Optional.ofNullable(ReflectionUtils.findField(type, CREATED_BY_FILTER));
		this.createdDateField = Optional.ofNullable(ReflectionUtils.findField(type, CREATED_DATE_FILTER));
		this.lastModifiedByField = Optional.ofNullable(ReflectionUtils.findField(type, LAST_MODIFIED_BY_FILTER));
		this.lastModifiedDateField = Optional.ofNullable(ReflectionUtils.findField(type, LAST_MODIFIED_DATE_FILTER));

		assertValidDateFieldType(createdDateField);
		assertValidDateFieldType(lastModifiedDateField);
	}

	/**
	 * 解析实体类的审计相关注解元数据,并保存到缓存中
	 */
	public static AnnotationAuditingMetadata getMetadata(Class<?> type) {
		return metadataCache.computeIfAbsent(type, AnnotationAuditingMetadata::new);
	}
	
	// 省略其他

}

AnnotationAuditingMetadata主要解析实体类中添加的审计相关注解的属性的Field。

小结

以上为本篇分享的全部内容,以下做一个小结:

1)JPA的提供了持久化的监听回调注解;

2)Spring解析实体类时,会解析实体类中添加的监听回调注解的监听器;或者实体类中的@EntityListeners注解中的监听器,并归类存放在FastSessionServices中,然后将FastSessionServices传给SessionImpl对象;

对于Auditing,监听器为AuditingEntityListener,添加了@PrePersist和@PreUpdate,在新增和修改之前回调。

3)Auditing审计功能通过添加@EnableJpaAuditing注解,自动为AuditingEntityListener添加AuditHandler对象;

4)AuditHandler对象提供了对当前执行持久化对象的审计相关注解的属性获取、审计人获取;

5)JPA通过SessionImpl执行新增或修改操作时,会调用FastSessionServices中对应操作类型的监听器,从而执行AuditingEntityListener的方法;

6)AuditingEntityListener通过AuditHandler及当前的实体类,通过反射,为实体类的审计属性赋值;

关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。

相关推荐
JingAi_jia9175 个月前
【源码】SpringBoot编程式事务使用及执行原理
spring源码·spring事务·transaction·springboot源码·spring事务源码·spring编程式事务
tmax52HZ5 个月前
SpringBoot源码(自动装配、内嵌Tomcat)
springboot·springboot自动装配·springboot源码·内嵌tomcat·tomcat源码·钩子函数·springboot依赖管理
smart哥1 年前
JDK并发修改异常的一个“BUG“
java·spring源码
泠青沼~1 年前
【Spring】条件注解
java·后端·spring·gradle·spring源码
我才是真的封不觉1 年前
爆肝spring源码笔记
spring·spring源码