package com.baidu.disconf.client.scan.inner.statically.strategy.impl; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.reflections.Reflections; import org.reflections.scanners.FieldAnnotationsScanner; import org.reflections.scanners.MethodAnnotationsScanner; import org.reflections.scanners.MethodParameterScanner; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.baidu.disconf.client.common.annotations.DisconfActiveBackupService; import com.baidu.disconf.client.common.annotations.DisconfFile; import com.baidu.disconf.client.common.annotations.DisconfFileItem; import com.baidu.disconf.client.common.annotations.DisconfItem; import com.baidu.disconf.client.common.annotations.DisconfUpdateService; import com.baidu.disconf.client.common.constants.Constants; import com.baidu.disconf.client.common.update.IDisconfUpdatePipeline; import com.baidu.disconf.client.scan.inner.common.ScanVerify; import com.baidu.disconf.client.scan.inner.statically.model.ScanStaticModel; import com.baidu.disconf.client.scan.inner.statically.strategy.ScanStaticStrategy; import com.google.common.base.Predicate; /** * Created by knightliao on 15/1/23. * <p/> * 扫描静态注解,并且进行分析整合数据 * <p/> * 使用 Reflection Lib */ public class ReflectionScanStatic implements ScanStaticStrategy { protected static final Logger LOGGER = LoggerFactory.getLogger(ScanStaticStrategy.class); /** * 扫描想要的类 */ @Override public ScanStaticModel scan(List<String> packNameList) { // 基本信息 ScanStaticModel scanModel = scanBasicInfo(packNameList); // 分析 analysis(scanModel); return scanModel; } /** * 通过扫描,获取反射对象 */ private Reflections getReflection(List<String> packNameList) { // // filter // FilterBuilder filterBuilder = new FilterBuilder().includePackage(Constants.DISCONF_PACK_NAME); for (String packName : packNameList) { filterBuilder = filterBuilder.includePackage(packName); } Predicate<String> filter = filterBuilder; // // urls // Collection<URL> urlTotals = new ArrayList<URL>(); for (String packName : packNameList) { Set<URL> urls = ClasspathHelper.forPackage(packName); urlTotals.addAll(urls); } // Reflections reflections = new Reflections(new ConfigurationBuilder().filterInputsBy(filter) .setScanners(new SubTypesScanner().filterResultsBy(filter), new TypeAnnotationsScanner() .filterResultsBy(filter), new FieldAnnotationsScanner() .filterResultsBy(filter), new MethodAnnotationsScanner() .filterResultsBy(filter), new MethodParameterScanner()).setUrls(urlTotals)); return reflections; } /** * 分析出一些关系 出来 */ private void analysis(ScanStaticModel scanModel) { // 分析出配置文件MAP analysis4DisconfFile(scanModel); } /** * 分析出配置文件与配置文件中的Field的Method的MAP */ private void analysis4DisconfFile(ScanStaticModel scanModel) { Map<Class<?>, Set<Method>> disconfFileItemMap = new HashMap<Class<?>, Set<Method>>(); // // 配置文件MAP // Set<Class<?>> classdata = scanModel.getDisconfFileClassSet(); for (Class<?> classFile : classdata) { disconfFileItemMap.put(classFile, new HashSet<Method>()); } // // 将配置文件与配置文件中的配置项进行关联 // Set<Method> af1 = scanModel.getDisconfFileItemMethodSet(); for (Method method : af1) { Class<?> thisClass = method.getDeclaringClass(); if (disconfFileItemMap.containsKey(thisClass)) { Set<Method> fieldSet = disconfFileItemMap.get(thisClass); fieldSet.add(method); disconfFileItemMap.put(thisClass, fieldSet); } else { LOGGER.error("cannot find CLASS ANNOTATION " + DisconfFile.class.getName() + " for disconf file item: " + method.toString()); } } // // 最后的校验 // Iterator<Class<?>> iterator = disconfFileItemMap.keySet().iterator(); while (iterator.hasNext()) { Class<?> classFile = iterator.next(); // 校验是否所有配置文件都含有配置 if (disconfFileItemMap.get(classFile).isEmpty()) { LOGGER.info("disconf file hasn't any items: " + classFile.getName()); continue; } // 校验配置文件类型是否合适(目前只支持.properties类型) DisconfFile disconfFile = classFile.getAnnotation(DisconfFile.class); boolean fileTypeRight = ScanVerify.isDisconfFileTypeRight(disconfFile); if (!fileTypeRight) { LOGGER.warn("now do not support this file type" + disconfFile.toString()); continue; } } // 设置 scanModel.setDisconfFileItemMap(disconfFileItemMap); } /** * 扫描基本信息 */ private ScanStaticModel scanBasicInfo(List<String> packNameList) { ScanStaticModel scanModel = new ScanStaticModel(); // // 扫描对象 // Reflections reflections = getReflection(packNameList); scanModel.setReflections(reflections); // // 获取DisconfFile class // Set<Class<?>> classdata = reflections.getTypesAnnotatedWith(DisconfFile.class); scanModel.setDisconfFileClassSet(classdata); // // 获取DisconfFileItem method // Set<Method> af1 = reflections.getMethodsAnnotatedWith(DisconfFileItem.class); scanModel.setDisconfFileItemMethodSet(af1); // // 获取DisconfItem method // af1 = reflections.getMethodsAnnotatedWith(DisconfItem.class); scanModel.setDisconfItemMethodSet(af1); // // 获取DisconfActiveBackupService // classdata = reflections.getTypesAnnotatedWith(DisconfActiveBackupService.class); scanModel.setDisconfActiveBackupServiceClassSet(classdata); // // 获取DisconfUpdateService // classdata = reflections.getTypesAnnotatedWith(DisconfUpdateService.class); scanModel.setDisconfUpdateService(classdata); // update pipeline Set<Class<? extends IDisconfUpdatePipeline>> iDisconfUpdatePipeline = reflections.getSubTypesOf (IDisconfUpdatePipeline .class); if (iDisconfUpdatePipeline != null && iDisconfUpdatePipeline.size() != 0) { scanModel.setiDisconfUpdatePipeline((Class<IDisconfUpdatePipeline>) iDisconfUpdatePipeline .toArray()[0]); } return scanModel; } }