DATACMNS-461 - Refactorings in auditing configuration support.

Cleaned up configuration setup. AuditingBeanDefinitionRegistrarSupport now exposes a getAuditingHandlerBeanName() method to determine the bean name to be used for the AuditingHandler.
This commit is contained in:
Oliver Gierke
2014-03-05 19:10:32 +01:00
parent b5727d4bf2
commit 324cee8cf0
8 changed files with 200 additions and 130 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,43 +15,71 @@
*/
package org.springframework.data.auditing.config;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.domain.AuditorAware;
import java.lang.annotation.Annotation;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
/**
* Configuration information for auditing.
* Default implementation for {@link AuditingConfiguration}.
*
* @author Ranie Jade Ramiso
* @author Thomas Darimont
* @author Oliver Gierke
*/
public interface AnnotationAuditingConfiguration {
public class AnnotationAuditingConfiguration implements AuditingConfiguration {
private final AnnotationAttributes attributes;
/**
* Returns the bean name of the {@link AuditorAware} instance to be used..
* Creates a new instance of {@link AnnotationAuditingConfiguration} for the given {@link AnnotationMetadata} and
* annotation type.
*
* @return
* @param metadata must not be {@literal null}.
* @param annotation must not be {@literal null}.
*/
String getAuditorAwareRef();
public AnnotationAuditingConfiguration(AnnotationMetadata metadata, Class<? extends Annotation> annotation) {
/**
* Returns whether the creation and modification dates shall be set. Defaults to {@literal true}.
*
* @return
*/
boolean isSetDates();
Assert.notNull(metadata, "AnnotationMetadata must not be null!");
Assert.notNull(annotation, "Annotation must not be null!");
/**
* Returns whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
*
* @return
*/
boolean isModifyOnCreate();
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(annotation.getName()));
}
/**
* Returns the bean name of the {@link DateTimeProvider} to be used.
*
* @return
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AuditingConfiguration#getAuditorAwareRef()
*/
String getDateTimeProviderRef();
@Override
public String getAuditorAwareRef() {
return attributes.getString("auditorAwareRef");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AuditingConfiguration#isSetDates()
*/
@Override
public boolean isSetDates() {
return attributes.getBoolean("setDates");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AuditingConfiguration#getDateTimeProviderRef()
*/
@Override
public String getDateTimeProviderRef() {
return attributes.getString("dateTimeProviderRef");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AuditingConfiguration#isModifyOnCreate()
*/
@Override
public boolean isModifyOnCreate() {
return attributes.getBoolean("modifyOnCreate");
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing.config;
import java.lang.annotation.Annotation;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
/**
* Default implementation for {@link AnnotationAuditingConfiguration}.
*
* @author Ranie Jade Ramiso
* @author Thomas Darimont
* @author Oliver Gierke
*/
public class AnnotationAuditingConfigurationSupport implements AnnotationAuditingConfiguration {
private final AnnotationAttributes attributes;
/**
* Creates a new instance of {@link AnnotationAuditingConfigurationSupport} for the given {@link AnnotationMetadata}
* and annotation type.
*
* @param metadata must not be {@literal null}.
* @param annotation must not be {@literal null}.
*/
public AnnotationAuditingConfigurationSupport(AnnotationMetadata metadata, Class<? extends Annotation> annotation) {
Assert.notNull(metadata, "AnnotationMetadata must not be null!");
Assert.notNull(annotation, "Annotation must not be null!");
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(annotation.getName()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AnnotationAuditingConfiguration#getAuditorAwareRef()
*/
@Override
public String getAuditorAwareRef() {
return attributes.getString("auditorAwareRef");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AnnotationAuditingConfiguration#isSetDates()
*/
@Override
public boolean isSetDates() {
return attributes.getBoolean("setDates");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AnnotationAuditingConfiguration#getDateTimeProviderRef()
*/
@Override
public String getDateTimeProviderRef() {
return attributes.getString("dateTimeProviderRef");
}
/*
* (non-Javadoc)
* @see org.springframework.data.auditing.config.AnnotationAuditingConfiguration#isModifyOnCreate()
*/
@Override
public boolean isModifyOnCreate() {
return attributes.getBoolean("modifyOnCreate");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
@@ -37,7 +36,7 @@ import org.springframework.util.StringUtils;
/**
* A {@link ImportBeanDefinitionRegistrar} that serves as a base class for store specific implementations for
* configuring audit support. Registers a {@link AuditingHandler} based on the provided configuration(
* {@link AnnotationAuditingConfiguration}).
* {@link AuditingConfiguration}).
*
* @author Ranie Jade Ramiso
* @author Thomas Darimont
@@ -72,13 +71,13 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
* @return
*/
private AbstractBeanDefinition registerAuditHandlerBeanDefinition(BeanDefinitionRegistry registry,
AnnotationAuditingConfiguration configuration) {
AuditingConfiguration configuration) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
Assert.notNull(configuration, "AnnotationAuditingConfiguration must not be null!");
Assert.notNull(configuration, "AuditingConfiguration must not be null!");
AbstractBeanDefinition ahbd = getAuditHandlerBeanDefinitionBuilder(configuration).getBeanDefinition();
registry.registerBeanDefinition(BeanDefinitionReaderUtils.generateBeanName(ahbd, registry), ahbd);
registry.registerBeanDefinition(getAuditingHandlerBeanName(), ahbd);
return ahbd;
}
@@ -89,9 +88,9 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
* @param configuration must not be {@literal null}.
* @return
*/
protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AnnotationAuditingConfiguration configuration) {
protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(AuditingConfiguration configuration) {
Assert.notNull(configuration, "AnnotationAuditingConfiguration must not be null!");
Assert.notNull(configuration, "AuditingConfiguration must not be null!");
return configureDefaultAuditHandlerAttributes(configuration,
BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class));
@@ -99,13 +98,13 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
/**
* Configures the given {@link BeanDefinitionBuilder} with the default attributes from the given
* {@link AnnotationAuditingConfiguration}.
* {@link AuditingConfiguration}.
*
* @param configuration must not be {@literal null}.
* @param builder must not be {@literal null}.
* @return the builder with the audit attributes configured.
*/
protected BeanDefinitionBuilder configureDefaultAuditHandlerAttributes(AnnotationAuditingConfiguration configuration,
protected BeanDefinitionBuilder configureDefaultAuditHandlerAttributes(AuditingConfiguration configuration,
BeanDefinitionBuilder builder) {
if (StringUtils.hasText(configuration.getAuditorAwareRef())) {
@@ -124,6 +123,8 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
builder.addPropertyValue(DATE_TIME_PROVIDER, CurrentDateTimeProvider.INSTANCE);
}
builder.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
return builder;
}
@@ -133,8 +134,8 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
* @param annotationMetadata will never be {@literal null}.
* @return
*/
protected AnnotationAuditingConfiguration getConfiguration(AnnotationMetadata annotationMetadata) {
return new AnnotationAuditingConfigurationSupport(annotationMetadata, getAnnotation());
protected AuditingConfiguration getConfiguration(AnnotationMetadata annotationMetadata) {
return new AnnotationAuditingConfiguration(annotationMetadata, getAnnotation());
}
/**
@@ -145,12 +146,21 @@ public abstract class AuditingBeanDefinitionRegistrarSupport implements ImportBe
protected abstract Class<? extends Annotation> getAnnotation();
/**
* @param auditingHandlerDefinition
* @param registry
* Register the listener to eventually trigger the {@link AuditingHandler}.
*
* @param auditingHandlerDefinition will never be {@literal null}.
* @param registry will never be {@literal null}.
*/
protected abstract void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
BeanDefinitionRegistry registry);
/**
* Return the name to be used to register the {@link AuditingHandler} under.
*
* @return
*/
protected abstract String getAuditingHandlerBeanName();
/**
* Registers the given {@link AbstractBeanDefinition} as infrastructure bean under the given id.
*

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.auditing.config;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.domain.AuditorAware;
/**
* Configuration information for auditing.
*
* @author Ranie Jade Ramiso
* @author Thomas Darimont
* @author Oliver Gierke
*/
public interface AuditingConfiguration {
/**
* Returns the bean name of the {@link AuditorAware} instance to be used..
*
* @return
*/
String getAuditorAwareRef();
/**
* Returns whether the creation and modification dates shall be set. Defaults to {@literal true}.
*
* @return
*/
boolean isSetDates();
/**
* Returns whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
*
* @return
*/
boolean isModifyOnCreate();
/**
* Returns the bean name of the {@link DateTimeProvider} to be used.
*
* @return
*/
String getDateTimeProviderRef();
}

View File

@@ -63,6 +63,7 @@ public class AuditingHandlerBeanDefinitionParser extends AbstractSingleBeanDefin
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String auditorAwareRef = element.getAttribute(AUDITOR_AWARE_REF);
if (StringUtils.hasText(auditorAwareRef)) {
builder.addPropertyValue("auditorAware", createLazyInitTargetSourceBeanDefinition(auditorAwareRef));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,10 @@
*/
package org.springframework.data.config;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
@@ -29,6 +32,7 @@ import org.w3c.dom.Element;
public class IsNewAwareAuditingHandlerBeanDefinitionParser extends AuditingHandlerBeanDefinitionParser {
private final String isNewStrategyFactoryBeanId;
private String resolvedBeanName;
/**
* Creates a new {@link IsNewAwareAuditingHandlerBeanDefinitionParser}.
@@ -41,6 +45,15 @@ public class IsNewAwareAuditingHandlerBeanDefinitionParser extends AuditingHandl
this.isNewStrategyFactoryBeanId = isNewStrategyFactoryBeanId;
}
/**
* Returns the bean name that was used to register the {@link IsNewAwareAuditingHandler}.
*
* @return the resolvedBeanName
*/
public String getResolvedBeanName() {
return resolvedBeanName;
}
/*
* (non-Javadoc)
* @see org.springframework.data.config.AuditingHandlerBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
@@ -58,7 +71,18 @@ public class IsNewAwareAuditingHandlerBeanDefinitionParser extends AuditingHandl
protected void doParse(Element element, BeanDefinitionBuilder builder) {
builder.addConstructorArgReference(isNewStrategyFactoryBeanId);
super.doParse(element, builder);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
this.resolvedBeanName = super.resolveId(element, definition, parserContext);
return resolvedBeanName;
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.data.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
@@ -127,4 +128,23 @@ public abstract class ParsingUtils {
definition.setSource(source);
return definition;
}
/**
* Returns a {@link BeanDefinition} for an {@link ObjectFactoryCreatingFactoryBean} pointing to the bean with the
* given name.
*
* @param targetBeanName must not be {@literal null} or empty.
* @param source
* @return
*/
public static AbstractBeanDefinition getObjectFactoryBeanDefinition(String targetBeanName, Object source) {
Assert.hasText(targetBeanName, "Target bean name must not be null or empty!");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ObjectFactoryCreatingFactoryBean.class);
builder.addPropertyValue("targetBeanName", targetBeanName);
builder.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
return getSourceBeanDefinition(builder, source);
}
}