diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java index b73477e11..448b597e9 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java @@ -53,6 +53,8 @@ public abstract class CdiRepositoryBean implements Bean, PassivationCapabl private final BeanManager beanManager; private final String passivationId; + private transient T repoInstance; + /** * Creates a new {@link CdiRepositoryBean}. * @@ -107,11 +109,6 @@ public abstract class CdiRepositoryBean implements Bean, PassivationCapabl interfaces.add(repositoryType); interfaces.addAll(Arrays.asList(repositoryType.getInterfaces())); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Declaring types '%s' for repository '%s'.", interfaces.toString(), - repositoryType.getName())); - } - return new HashSet(interfaces); } @@ -128,17 +125,27 @@ public abstract class CdiRepositoryBean implements Bean, PassivationCapabl return (S) beanManager.getReference(bean, type, creationalContext); } + /** + * Forces the initialization of bean target. + */ + public final void initialize() { + create(beanManager.createCreationalContext(this)); + } + /* * (non-Javadoc) * @see javax.enterprise.context.spi.Contextual#create(javax.enterprise.context.spi.CreationalContext) */ public final T create(CreationalContext creationalContext) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Creating bean instance for repository type '%s'.", repositoryType.getName())); + if (this.repoInstance != null) { + LOGGER.debug("Returning eagerly created CDI repository instance for {}.", repositoryType.getName()); + return this.repoInstance; } - return create(creationalContext, repositoryType); + LOGGER.debug("Creating CDI repository bean instance for {}.", repositoryType.getName()); + this.repoInstance = create(creationalContext, repositoryType); + return repoInstance; } /* diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java index c65b52b0b..df211f8a5 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java @@ -25,7 +25,9 @@ import java.util.Set; import javax.enterprise.event.Observes; import javax.enterprise.inject.Any; import javax.enterprise.inject.Default; +import javax.enterprise.inject.spi.AfterDeploymentValidation; import javax.enterprise.inject.spi.AnnotatedType; +import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.util.AnnotationLiteral; @@ -33,6 +35,7 @@ import javax.inject.Qualifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.Repository; import org.springframework.data.repository.RepositoryDefinition; @@ -48,6 +51,7 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { private static final Logger LOGGER = LoggerFactory.getLogger(CdiRepositoryExtensionSupport.class); private final Map, Set> repositoryTypes = new HashMap, Set>(); + private final Set> eagerRepositories = new HashSet>(); /** * Implementation of a an observer which checks for Spring Data repository types and stores them in @@ -115,6 +119,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { return qualifiers; } + /** + * Triggers the eager initialization of beans registered for that behavior. + * + * @param event must not be {@literal null}. + * @param manager must not be {@literal null}. + * @see #registerBean(CdiRepositoryBean) + */ + void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager manager) { + + for (CdiRepositoryBean bean : eagerRepositories) { + + LOGGER.debug("Eagerly instantiating CDI repository bean for {}.", bean.getBeanClass()); + bean.initialize(); + } + } + /** * Provides access to all repository types as well as their qualifiers. * @@ -124,6 +144,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { return repositoryTypes.entrySet(); } + /** + * Registers the given {@link CdiRepositoryBean} for further general treatment by the infrastructure. In particular, + * this will cause repositories to be instantiated eagerly if marked as such. + * + * @param bean must not be {@literal null}. + * @see #afterDeploymentValidation(AfterDeploymentValidation, BeanManager) + */ + protected void registerBean(CdiRepositoryBean bean) { + + Class repositoryInterface = bean.getBeanClass(); + + if (AnnotationUtils.findAnnotation(repositoryInterface, Eager.class) != null) { + this.eagerRepositories.add(bean); + } + } + @SuppressWarnings("all") static class DefaultAnnotationLiteral extends AnnotationLiteral implements Default { diff --git a/src/main/java/org/springframework/data/repository/cdi/Eager.java b/src/main/java/org/springframework/data/repository/cdi/Eager.java new file mode 100644 index 000000000..3350176f7 --- /dev/null +++ b/src/main/java/org/springframework/data/repository/cdi/Eager.java @@ -0,0 +1,37 @@ +/* + * Copyright 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. + * 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.repository.cdi; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to mark repository interfaces to be instantiated eagerly in a CDI context. + * + * @author Oliver Gierke + * @since 1.7 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) +@Inherited +public @interface Eager { + +} diff --git a/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java b/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java index 389589b91..767e23734 100644 --- a/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java +++ b/src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java @@ -40,7 +40,9 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport { @SuppressWarnings({ "rawtypes", "unchecked" }) void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { for (Entry, Set> type : getRepositoryTypes()) { - afterBeanDiscovery.addBean(new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager)); + DummyCdiRepositoryBean bean = new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager); + registerBean(bean); + afterBeanDiscovery.addBean(bean); } }