Java tutorial
/* * Copyright: (c) 2004-2012 Mayo Foundation for Medical Education and * Research (MFMER). All rights reserved. MAYO, MAYO CLINIC, and the * triple-shield Mayo logo are trademarks and service marks of MFMER. * * Except as contained in the copyright notice above, or as used to identify * MFMER as the author of this software, the trade names, trademarks, service * marks, or product names of the copyright holder shall not be used in * advertising, promotion or otherwise in connection with this software without * prior written authorization of the copyright holder. * * 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 edu.mayo.cts2.framework.plugin.service.nlm.mybatis.osgi; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.Set; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.mapper.MapperFactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** * The Class MapperScannerConfigurer. * * @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a> */ public class MapperScannerConfigurer implements BeanFactoryPostProcessor, InitializingBean, ApplicationContextAware { private String basePackage; private boolean addToConfig = true; private SqlSessionFactory sqlSessionFactory; private SqlSessionTemplate sqlSessionTemplate; private Class<? extends Annotation> annotationClass; private Class<?> markerInterface; private ApplicationContext applicationContext; /** * Sets the base package. * * @param basePackage the new base package */ public void setBasePackage(String basePackage) { this.basePackage = basePackage; } /** * Sets the adds the to config. * * @param addToConfig the new adds the to config */ public void setAddToConfig(boolean addToConfig) { this.addToConfig = addToConfig; } /** * Sets the annotation class. * * @param annotationClass the new annotation class */ public void setAnnotationClass(Class<? extends Annotation> annotationClass) { this.annotationClass = annotationClass; } /** * Sets the marker interface. * * @param superClass the new marker interface */ public void setMarkerInterface(Class<?> superClass) { this.markerInterface = superClass; } /** * Sets the sql session factory. * * @param sqlSessionFactory the new sql session factory */ public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } /** * Sets the sql session template. * * @param sqlSessionTemplate the new sql session template */ public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @Override public void setApplicationContext(final ApplicationContext applicationContext) { this.applicationContext = applicationContext; } /** * {@inheritDoc} */ public void afterPropertiesSet() throws Exception { Assert.notNull(this.basePackage, "Property 'basePackage' is required"); } /** * {@inheritDoc} */ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { Scanner scanner = new Scanner((BeanDefinitionRegistry) beanFactory); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); } /** * The Class Scanner. * * @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a> */ private final class Scanner extends ClassPathBeanDefinitionScanner { /** * Instantiates a new scanner. * * @param registry the registry */ public Scanner(BeanDefinitionRegistry registry) { super(registry); setResourceLoader(applicationContext); } /** * Configures parent scanner to search for the right interfaces. It can search for all * interfaces or just for those that extends a markerInterface or/and those annotated with * the annotationClass */ @Override protected void registerDefaultFilters() { boolean acceptAllInterfaces = true; // if specified, use the given annotation and / or marker interface if (MapperScannerConfigurer.this.annotationClass != null) { addIncludeFilter(new AnnotationTypeFilter(MapperScannerConfigurer.this.annotationClass)); acceptAllInterfaces = false; } // override AssignableTypeFilter to ignore matches on the actual marker interface if (MapperScannerConfigurer.this.markerInterface != null) { addIncludeFilter(new AssignableTypeFilter(MapperScannerConfigurer.this.markerInterface) { @Override protected boolean matchClassName(String className) { return false; } }); acceptAllInterfaces = false; } if (acceptAllInterfaces) { // default include filter that accepts all classes addIncludeFilter(new TypeFilter() { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return true; } }); } // always exclude interfaces with no methods addExcludeFilter(new TypeFilter() { public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { ClassMetadata classMetadata = metadataReader.getClassMetadata(); Class<?> candidateClass = null; try { candidateClass = getClass().getClassLoader().loadClass(classMetadata.getClassName()); } catch (ClassNotFoundException ex) { return false; } if (candidateClass.getMethods().length == 0) { return true; } else { return false; } } }); } /** * Calls the parent search that will search and register all the candidates. Then the * registered objects are post processed to set them as MapperFactoryBeans * * @param basePackages the base packages * @return the sets the */ @Override protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + MapperScannerConfigurer.this.basePackage + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName()); definition.setBeanClass(MapperFactoryBean.class); definition.getPropertyValues().add("addToConfig", MapperScannerConfigurer.this.addToConfig); if (MapperScannerConfigurer.this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", MapperScannerConfigurer.this.sqlSessionFactory); } if (MapperScannerConfigurer.this.sqlSessionTemplate != null) { definition.getPropertyValues().add("sqlSessionTemplate", MapperScannerConfigurer.this.sqlSessionTemplate); } } } return beanDefinitions; } /* (non-Javadoc) * @see org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition) */ @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent()); } /* (non-Javadoc) * @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner#checkCandidate(java.lang.String, org.springframework.beans.factory.config.BeanDefinition) */ @Override protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException { if (super.checkCandidate(beanName, beanDefinition)) { return true; } else { logger.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!"); return false; } } } }