Java tutorial
/* Copyright 2010 Marcel Overdijk * * 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 com.deq.spring; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import com.googlecode.objectify.ObjectifyFactory; /** * {@link org.springframework.beans.factory.FactoryBean} that creates an * {@link com.googlecode.objectify.ObjectifyFactory}. * * <p> * The simplest way to use this class is to provide a basePackage and it will * scan for classes annotated with {@link javax.perjavax.persistence.Entity} or * {@link com.googlecode.objectify.annotation.Entity}. Found classes will then * be registered in the ObjectifyFactory. * * <p> * Example configuration: * * <pre class="code"> * <bean class="com.googlecode.objectify.spring.ObjectifyFactoryBean" * p:basePackage="com.mycompany.domain" /> * </pre> * * <p> * Multiple basePackages can be provided as well: * * <pre class="code"> * <bean class="com.googlecode.objectify.spring.ObjectifyFactoryBean" * p:basePackage="com.mycompany.domain;com.othercompany.domain" /> * </pre> * * <p> * Alternatively it is also possible to explicitly define classes to be * registered in the ObjectifyFactory. This approach is useful when you are * concerned by App Engine's cold startup times and are not using the * context:component-scan option to autodetect classes. * * <p> * Example configuration: * * <pre class="code"> * <bean class="com.googlecode.objectify.spring.ObjectifyFactoryBean"> * <property name="classes"> * <list> * <value>com.mycompany.domain.Car</value> * <value>com.mycompany.domain.Person</value> * </list> * </property> * </bean> * </pre> * * @author Marcel Overdijk * @see #setBasePackage(String) * @see #setClasses(List) * @see com.googlecode.objectify.ObjectifyFactory * @see javax.perjavax.persistence.Entity */ public class ObjectifyFactoryBean implements FactoryBean<ObjectifyFactory>, InitializingBean { protected final Log logger = LogFactory.getLog(getClass()); private ObjectifyFactory objectifyFactory; private String basePackage; private List<Class<?>> classes; @Override public ObjectifyFactory getObject() throws Exception { return objectifyFactory; } @Override public Class<? extends ObjectifyFactory> getObjectType() { return ObjectifyFactory.class; } @Override public boolean isSingleton() { return true; } @Override public void afterPropertiesSet() throws Exception { if (logger.isInfoEnabled()) { logger.info("Initialization started"); } final long startTime = System.currentTimeMillis(); if (classes == null) { classes = new ArrayList<Class<?>>(); } if ((basePackage != null) && (basePackage.length() > 0)) { classes.addAll(doScan()); } objectifyFactory = new ObjectifyFactory(); for (final Class<?> clazz : classes) { objectifyFactory.register(clazz); if (logger.isInfoEnabled()) { logger.info("Registered entity class [" + clazz.getName() + "]"); } } if (logger.isInfoEnabled()) { final long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Initialization completed in " + elapsedTime + " ms"); } } protected List<Class<?>> doScan() { final List<Class<?>> classes = new ArrayList<Class<?>>(); final String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (final String basePackage : basePackages) { if (logger.isInfoEnabled()) { logger.info("Scanning package [" + basePackage + "]"); } final ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( false); scanner.addIncludeFilter(new AnnotationTypeFilter(com.googlecode.objectify.annotation.Entity.class)); scanner.addIncludeFilter(new AnnotationTypeFilter(com.googlecode.objectify.annotation.Subclass.class)); scanner.addIncludeFilter(new AnnotationTypeFilter(javax.persistence.Entity.class)); final Set<BeanDefinition> candidates = scanner.findCandidateComponents(basePackage); for (final BeanDefinition candidate : candidates) { final Class<?> clazz = ClassUtils.resolveClassName(candidate.getBeanClassName(), ClassUtils.getDefaultClassLoader()); classes.add(clazz); } } return classes; } public void setBasePackage(final String basePackage) { this.basePackage = basePackage; } public void setClasses(final List<Class<?>> classes) { this.classes = classes; } }