package org.onetwo.common.spring; import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.function.BiConsumer; import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; import org.onetwo.apache.io.IOUtils; import org.onetwo.common.exception.BaseException; import org.onetwo.common.expr.Expression; import org.onetwo.common.expr.ExpressionFacotry; import org.onetwo.common.file.FileUtils; import org.onetwo.common.log.JFishLoggerFactory; import org.onetwo.common.propconf.JFishProperties; import org.onetwo.common.propconf.PropUtils; import org.onetwo.common.reflect.BeanToMapConvertor; import org.onetwo.common.reflect.BeanToMapConvertor.BeanToMapBuilder; import org.onetwo.common.reflect.BeanToMapConvertor.ValuePutter; import org.onetwo.common.reflect.PropertyContext; import org.onetwo.common.reflect.ReflectUtils; import org.onetwo.common.spring.config.JFishPropertyPlaceholder; import org.onetwo.common.spring.utils.BeanMapWrapper; import org.onetwo.common.spring.utils.JFishPropertiesFactoryBean; import org.onetwo.common.spring.utils.MapToBeanConvertor; import org.onetwo.common.utils.Assert; import org.onetwo.common.utils.LangUtils; import org.onetwo.common.utils.StringUtils; import org.slf4j.Logger; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeansException; import org.springframework.beans.ConfigurablePropertyAccessor; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.HierarchicalBeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.beans.factory.config.SingletonBeanRegistry; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodIntrospector; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.Property; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.env.PropertyResolver; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.NumberFormat; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.FormattingConversionService; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils.MethodFilter; import org.springframework.util.ResourceUtils; import org.springframework.web.multipart.MultipartFile; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /**** * 可通过这个类手动获取spring容器里注册的bean * @author weishao * */ @SuppressWarnings({"unchecked"}) final public class SpringUtils { protected static Logger logger = JFishLoggerFactory.getLogger(SpringUtils.class); private static String ACTIVE_PROFILES = "spring.profiles.active"; // private static String CLASSPATH = "classpath:"; private static final MapToBeanConvertor MAP_TO_BEAN = MapToBeanConvertor.builder().build(); private static final FormattingConversionService CONVERSION_SERVICE = new DefaultFormattingConversionService(); private static final BeanToMapConvertor BEAN_TO_MAP_CONVERTOR = BeanToMapBuilder.newBuilder() .enableFieldNameAnnotation() .build(); public static final Expression DOLOR = ExpressionFacotry.newExpression("${", "}"); private SpringUtils(){ } public static int higherThan(int order) { return higherThan(order, 10); } public static int higherThan(int order, int step) { return order - step; } public static int lowerThan(int order) { return lowerThan(order, 10); } public static int lowerThan(int order, int step) { return order + step; } public static FormattingConversionService getFormattingConversionService(){ return CONVERSION_SERVICE; } public static <T> T convertValue(Object value, Class<T> targetType){ T res = (T)getFormattingConversionService().convert(value, TypeDescriptor.valueOf(value.getClass()), TypeDescriptor.valueOf(targetType)); return res; } public static Object convertValue(Object value, Class<?> clazz, String name, boolean byProperty){ TypeDescriptor td = byProperty?typeDescriptorForPerperty(clazz, name):typeDescriptorForField(clazz, name); Object res = getFormattingConversionService().convert(value, TypeDescriptor.valueOf(value.getClass()), td); return res; } /*public static Map<String, Object> toFlatMap(Object obj) { return toFlatMap(obj, o->!LangUtils.isSimpleTypeObject(o)); }*/ public static Map<String, Object> toFlatMap(Object obj) { Map<String, Object> map = Maps.newHashMap(); ConsumableValuePutter putter = new ConsumableValuePutter((k, v) -> { map.put(k, v); }); /*BEAN_TO_MAP_CONVERTOR.flatObject("", obj, (k, v, ctx)->{ Object value = v; TypeDescriptor sourceType = null; if(v.getClass()!=String.class){ Field field = ctx.getField(); if(field!=null && (field.getAnnotation(DateTimeFormat.class)!=null || field.getAnnotation(NumberFormat.class)!=null) ){ sourceType = new TypeDescriptor(field); } if(sourceType==null){ sourceType = new TypeDescriptor(new Property(ctx.getSource().getClass(), ctx.getProperty().getReadMethod(), ctx.getProperty().getWriteMethod())); } value = getFormattingConversionService().convert(v, sourceType, TypeDescriptor.valueOf(String.class)); } map.put(k, value); });*/ BEAN_TO_MAP_CONVERTOR.flatObject("", obj, putter); return map; } public static class ConsumableValuePutter implements ValuePutter { private final BiConsumer<String, Object> consumer; public ConsumableValuePutter(BiConsumer<String, Object> consumer) { super(); this.consumer = consumer; } @Override public void put(String k, Object v, PropertyContext ctx) { Object value = v; TypeDescriptor sourceType = null; if(v.getClass()!=String.class){ Field field = ctx.getField(); if(field!=null && (field.getAnnotation(DateTimeFormat.class)!=null || field.getAnnotation(NumberFormat.class)!=null) ){ sourceType = new TypeDescriptor(field); } if(sourceType==null){ sourceType = new TypeDescriptor(new Property(ctx.getSource().getClass(), ctx.getProperty().getReadMethod(), ctx.getProperty().getWriteMethod())); } value = getFormattingConversionService().convert(v, sourceType, TypeDescriptor.valueOf(String.class)); } // map.put(k, value); this.consumer.accept(k, value); } } public static TypeDescriptor typeDescriptorForPerperty(Class<?> clazz, String propertyName){ PropertyDescriptor pd = ReflectUtils.getPropertyDescriptor(clazz, propertyName); TypeDescriptor td = new TypeDescriptor(new Property(clazz, pd.getReadMethod(), pd.getWriteMethod())); return td; } public static TypeDescriptor typeDescriptorForField(Class<?> clazz, String fieldName){ Field field = ReflectUtils.findField(clazz, fieldName); TypeDescriptor td = new TypeDescriptor(field); return td; } public static void setProfiles(String profiles){ System.setProperty(ACTIVE_PROFILES, profiles); } public static String getProfiles(){ return System.getProperty(ACTIVE_PROFILES); } public static void addProfiles(String... profiles){ if(LangUtils.isEmpty(profiles)) return ; String existProfiles = getProfiles(); String newProfiles = StringUtils.join(profiles, ","); if(StringUtils.isNotBlank(existProfiles)){ newProfiles = existProfiles + newProfiles; } setProfiles(newProfiles); } public static class WithAnnotationBeanData<T extends Annotation> { final private T annotation; final private String name; final private Object bean; public WithAnnotationBeanData(T annotation, String name, Object bean) { super(); this.annotation = annotation; this.name = name; this.bean = bean; } public T getAnnotation() { return annotation; } public String getName() { return name; } public Object getBean() { return bean; } } public static <T extends Annotation> List<WithAnnotationBeanData<T>> getBeansWithAnnotation(ApplicationContext applicationContext, Class<T> annotationType){ Map<String, Object> beans = applicationContext.getBeansWithAnnotation(annotationType); return beans.entrySet().stream().map(e->{ T annotation = AnnotationUtils.findAnnotation(e.getValue().getClass(), annotationType); WithAnnotationBeanData<T> data = new WithAnnotationBeanData<T>(annotation, e.getKey(), e.getValue()); return data; }) .collect(Collectors.toList()); } public static <T> T getBeanWithAnnotation(ApplicationContext applicationContext, Class<? extends Annotation> annotationType) { List<T> beans = (List<T>)getBeansWithAnnotation(applicationContext, annotationType).stream().map(d -> { return d.getBean(); }).collect(Collectors.toList()); return LangUtils.isEmpty(beans)?null:beans.get(0); } public static <T> List<T> getBeans(ListableBeanFactory appContext, Class<T> clazz) { Map<String, T> beanMaps = BeanFactoryUtils.beansOfTypeIncludingAncestors(appContext, clazz); if(beanMaps==null || beanMaps.isEmpty()) return new ArrayList<>(); List<T> list = new ArrayList<T>(beanMaps.values()); AnnotationAwareOrderComparator.sort(list); return list; } public static <T> List<T> getBeans(ListableBeanFactory appContext, Class<?> clazz, ParameterizedTypeReference<T> typeRef) { List<T> list = (List<T>)getBeans(appContext, clazz); return list; } public static <T> Map<String, T> getBeansAsMap(ApplicationContext appContext, Class<T> clazz) { Map<String, T> beanMaps = BeanFactoryUtils.beansOfTypeIncludingAncestors(appContext, clazz); return beanMaps; } public static <T> T getBean(ListableBeanFactory appContext, Class<T> clazz) { List<T> beans = getBeans(appContext, clazz); return (T)LangUtils.getFirst(beans); } public static <T> T getBean(ApplicationContext appContext, String beanName) { return (T)appContext.getBean(beanName); } public static <T> T getHighestOrder(ApplicationContext appContext, Class<T> clazz){ List<T> list = getBeans(appContext, clazz); if(LangUtils.isEmpty(list)) return null; else return list.get(0); } public static <T> T getLowestOrder(ApplicationContext appContext, Class<T> clazz){ List<T> list = getBeans(appContext, clazz); if(LangUtils.isEmpty(list)) return null; else return list.get(list.size()-1); } public static PropertyPlaceholderConfigurer newApplicationConf(String... locations){ return newApplicationConf(true, locations); } public static PropertyPlaceholderConfigurer newApplicationConf(boolean searchSystemEnvironment, String... locations){ Assert.notEmpty(locations); PropertyPlaceholderConfigurer ppc = new JFishPropertyPlaceholder(); ppc.setIgnoreResourceNotFound(true); ppc.setIgnoreUnresolvablePlaceholders(true); ppc.setSearchSystemEnvironment(searchSystemEnvironment); List<Resource> resources = new ArrayList<Resource>(); for(String path : locations){ resources.add(new ClassPathResource(path)); } ppc.setLocations(resources.toArray(new Resource[resources.size()])); return ppc; } public static boolean isSpringConfPlaceholder(String value){ if(value.indexOf("${")!=-1 && value.indexOf("}")!=-1) return true; return false; } public static Resource newPathResource(String location){ Assert.hasText(location); Resource resource = null; if(location.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)){ String classpath = StringUtils.substringAfter(location, ResourceUtils.CLASSPATH_URL_PREFIX); resource = new ClassPathResource(classpath); }else{ resource = new FileSystemResource(location); } return resource; } public static Resource newClassPathResource(String location){ return new ClassPathResource(location); } public static Properties createProperties(String location, boolean throwIfError){ Assert.hasText(location); Resource res = new ClassPathResource(location); Properties prop = null; try { prop = PropUtils.loadProperties(res.getFile()); } catch (IOException e) { if(throwIfError) throw new BaseException("load properties error : " + e.getMessage()); else logger.error("ignore load this properties["+location+"] , error : " + e.getMessage()); } return prop; } public static JFishProperties loadAsJFishProperties(String... classpaths){ PropertiesFactoryBean pfb = createPropertiesBySptring(classpaths); try { pfb.afterPropertiesSet(); JFishProperties properties = (JFishProperties)pfb.getObject(); return properties; } catch (IOException e) { throw new BaseException("load config error: " + e.getMessage(), e); } } public static PropertiesFactoryBean createPropertiesBySptring(String...classpaths) { return createPropertiesBySptring(new JFishProperties(), classpaths); } public static PropertiesFactoryBean createPropertiesBySptring(JFishProperties properties, String...classpaths) { // PropertiesFactoryBean pfb = new PropertiesFactoryBean(); PropertiesFactoryBean pfb = new JFishPropertiesFactoryBean(properties); pfb.setIgnoreResourceNotFound(true); org.springframework.core.io.Resource[] resources = new org.springframework.core.io.Resource[classpaths.length]; int index = 0; for(String classpath : classpaths){ resources[index++] = classpath(classpath); } pfb.setLocations(resources); return pfb; } public static AutowireCapableBeanFactory findAutoWiringBeanFactory(ApplicationContext context) { if (context instanceof AutowireCapableBeanFactory) { return (AutowireCapableBeanFactory) context; } else if (context instanceof ConfigurableApplicationContext) { return ((ConfigurableApplicationContext) context).getBeanFactory(); } else if (context.getParent() != null) { return findAutoWiringBeanFactory(context.getParent()); } return null; } public static BeanDefinition createBeanDefinition(Class<?> beanClass, Object[] constructorArgs, Map<String, Object> properties){ BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(beanClass); if(constructorArgs!=null){ for(Object arg : constructorArgs){ bdb.addConstructorArgValue(arg); } } if(LangUtils.isNotEmpty(properties)){ for(Entry<String, Object> entry : properties.entrySet()){ bdb.addPropertyValue(entry.getKey(), entry.getValue()); } } return bdb.getBeanDefinition(); } public static <T> void autowireBean(ApplicationContext appContext, T existingBean){ appContext.getAutowireCapableBeanFactory().autowireBean(existingBean); } public static <T> void injectAndInitialize(ApplicationContext appContext, T bean) { injectAndInitialize(appContext.getAutowireCapableBeanFactory(), bean, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); } public static <T> void injectAndInitialize(AutowireCapableBeanFactory acb, T bean, int autowireMode) { acb.autowireBeanProperties(bean, autowireMode, false); initializeBean(acb, bean); } public static <T> void initializeBean(AutowireCapableBeanFactory acb, T bean) { String beanName = StringUtils.uncapitalize(bean.getClass().getSimpleName()); acb.initializeBean(bean, beanName); } public static <T> void initializeBean(ApplicationContext appContext, T bean) { String beanName = StringUtils.uncapitalize(bean.getClass().getSimpleName()); appContext.getAutowireCapableBeanFactory().initializeBean(bean, beanName); } public static <T> T registerBean(BeanFactory context, Class<?> beanClass, Object...params){ return registerBean(context, StringUtils.uncapitalize(beanClass.getSimpleName()), beanClass, params); } /*** * register and get bean * @author wayshall * @param context * @param beanName * @param beanClass * @param params * @return */ public static <T> T registerBean(BeanFactory context, String beanName, Class<?> beanClass, Object...params){ registerBeanDefinition(context, beanName, beanClass, params); T bean = (T) context.getBean(beanName); if(bean==null) throw new BaseException("register spring bean error : " + beanClass); return bean; } /*public static BeanDefinition registerBeanDefinition(ApplicationContext context, String beanName, Class<?> beanClass, Object...params){ BeanDefinitionRegistry bdr = getBeanDefinitionRegistry(context, true); return registerBeanDefinition(bdr, beanName, beanClass, params); } public static BeanDefinition registerBeanDefinition(BeanFactory context, String beanName, Class<?> beanClass, Object...params){ BeanDefinitionRegistry bdr = getBeanDefinitionRegistry(context, true); return registerBeanDefinition(bdr, beanName, beanClass, params); }*/ /*public static BeanDefinitionRegistry getBeanDefinitionRegistry(Object context, boolean throwIfNull){ BeanDefinitionRegistry bdr = null; if(ApplicationContext.class.isInstance(context)){ BeanFactory bf = ((ApplicationContext)context).getAutowireCapableBeanFactory(); if(BeanDefinitionRegistry.class.isInstance(bf)) bdr = (BeanDefinitionRegistry) bf; }else if(BeanDefinitionRegistry.class.isInstance(context)){ bdr = (BeanDefinitionRegistry) context; }else{ // } if(bdr==null && throwIfNull) throw new BaseException("this context can not rigister spring bean : " + context); return bdr; }*/ /**** * 注册bean定义 * @param bdr * @param beanName * @param beanClass * @param params * @return */ public static BeanDefinition registerBeanDefinition(Object context, String beanName, Class<?> beanClass, Object...params){ BeanDefinitionRegistry bdr = getBeanDefinitionRegistry(context, true); if(StringUtils.isBlank(beanName)){ beanName = StringUtils.uncapitalize(beanClass.getSimpleName()); } BeanDefinition bd = createBeanDefinition(beanClass, null, LangUtils.asMap(params)); bdr.registerBeanDefinition(beanName, bd); return bd; } /***** * 获取SingletonBeanRegistry * @param applicationContext * @return */ public static SingletonBeanRegistry getSingletonBeanRegistry(Object applicationContext){ Object bf = applicationContext; if(applicationContext instanceof AbstractApplicationContext){ bf = ((AbstractApplicationContext)applicationContext).getBeanFactory(); } if(bf==null || !SingletonBeanRegistry.class.isInstance(bf)){ return null; } SingletonBeanRegistry sbr = (SingletonBeanRegistry) bf; return sbr; } public static BeanDefinitionRegistry getBeanDefinitionRegistry(Object applicationContext){ return getBeanDefinitionRegistry(applicationContext, true); } public static BeanDefinitionRegistry getBeanDefinitionRegistry(Object applicationContext, boolean throwIfNull){ if(BeanDefinitionRegistry.class.isInstance(applicationContext)){ return (BeanDefinitionRegistry) applicationContext; } Object bf = applicationContext; if(applicationContext instanceof AbstractApplicationContext){ bf = ((AbstractApplicationContext)applicationContext).getBeanFactory(); } if(bf==null || !BeanDefinitionRegistry.class.isInstance(bf)){ if(throwIfNull){ throw new BaseException("this context can not rigister spring bean : " + applicationContext); }else{ return null; } } BeanDefinitionRegistry sbr = (BeanDefinitionRegistry) bf; return sbr; } public static void registerSingleton(BeanFactory applicationContext, String beanName, Object singletonObject){ getSingletonBeanRegistry(applicationContext).registerSingleton(beanName, singletonObject); } public static void registerAndInitSingleton(ApplicationContext applicationContext, String beanName, Object singletonObject){ getSingletonBeanRegistry(applicationContext).registerSingleton(beanName, singletonObject); injectAndInitialize(applicationContext, singletonObject); } public static Resource classpath(String path){ return new ClassPathResource(path); } public static InputStream classpathStream(String path){ try { return classpath(path).getInputStream(); } catch (IOException e) { throw new BaseException("read classpath file as stream error: " + path); } } public static BeanWrapper newBeanWrapper(Object obj){ BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(obj); bw.setAutoGrowNestedPaths(true); return bw; } public static ConfigurablePropertyAccessor newPropertyAccessor(Object obj, boolean directFieldAccess){ ConfigurablePropertyAccessor bw = directFieldAccess?PropertyAccessorFactory.forDirectFieldAccess(obj):PropertyAccessorFactory.forBeanPropertyAccess(obj); bw.setAutoGrowNestedPaths(true); return bw; } public static BeanWrapper newBeanMapWrapper(Object obj, Object...listElementTypes){ BeanWrapper bw = null; if(Map.class.isInstance(obj)){ bw = new BeanMapWrapper(obj, listElementTypes); }else{ bw = PropertyAccessorFactory.forBeanPropertyAccess(obj); } bw.setAutoGrowNestedPaths(true); return bw; } public static <T> T map2Bean(Map<String, ?> props, Class<T> beanClass){ T bean = ReflectUtils.newInstance(beanClass); return setMap2Bean(props, bean); } public static <T> T setMap2Bean(Map<String, ?> props, T bean){ Assert.notNull(bean); Assert.notNull(props); BeanWrapper bw = newBeanWrapper(bean); for(Entry<String, ?> entry : props.entrySet()){ if(bw.isWritableProperty(entry.getKey())){ bw.setPropertyValue(entry.getKey(), entry.getValue()); } } return bean; } /*public static BeanMapWrapper newBeanMapWrapper(Object obj){ BeanMapWrapper bw = new BeanMapWrapper(obj); return bw; }*/ public static Map<String, Object> beansOfAnnotationIncludingAncestors(ListableBeanFactory lbf, Class<? extends Annotation> annotationType) throws BeansException { Assert.notNull(lbf, "ListableBeanFactory must not be null"); Map<String, Object> result = new LinkedHashMap<String, Object>(); result.putAll(lbf.getBeansWithAnnotation(annotationType)); if (lbf instanceof HierarchicalBeanFactory) { HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf; if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) { Map<String, Object> parentResult = beansOfAnnotationIncludingAncestors( (ListableBeanFactory) hbf.getParentBeanFactory(), annotationType); for (Map.Entry<String, Object> entry : parentResult.entrySet()) { String beanName = entry.getKey(); if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) { result.put(beanName, entry.getValue()); } } } } return result; } public static String[] getConstructorNames(Class<?> clazz){ return getConstructorNames(clazz, 0); } public static String[] getConstructorNames(Class<?> clazz, int constructorIndex){ Constructor<?> targetConstructor = ReflectUtils.getConstructor(clazz, constructorIndex); return getConstructorNames(targetConstructor); } public static String[] getConstructorNames(Constructor<?> targetConstructor){ LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); return discoverer.getParameterNames(targetConstructor); } public static Class<?> getTargetClass(Object candidate) { Class<?> targetClass = AopUtils.getTargetClass(candidate); if(ClassUtils.isCglibProxyClass(targetClass)){ targetClass = candidate.getClass().getSuperclass(); } return targetClass; } public static boolean scanAnnotation(ApplicationContext applicationContext, Class<? extends Annotation> annoClass, BiConsumer<Object, Class<?>> consumer){ ListableBeanFactory beanFactory = (ListableBeanFactory)applicationContext.getAutowireCapableBeanFactory(); return scanAnnotation(beanFactory, annoClass, consumer); } /**** * * @author wayshall * @param beanFactory * @param annoClass * @param consumer * @return 如果找到指定注解的bean,则返回true,否则返回false */ public static boolean scanAnnotation(ListableBeanFactory beanFactory, Class<? extends Annotation> annoClass, BiConsumer<Object, Class<?>> consumer){ String[] beanNames = beanFactory.getBeanNamesForAnnotation(annoClass); for(String beanName : beanNames){ Object bean = beanFactory.getBean(beanName); Class<?> beanClass = SpringUtils.getTargetClass(bean); consumer.accept(bean, beanClass); } return ArrayUtils.isNotEmpty(beanNames); } public static AnnotationAttributes getAnnotationAttributes(AnnotatedTypeMetadata metadata, Class<?> annoType){ //support @AliasFor AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annoType.getName(), false)); return attributes; } public static Optional<AnnotationAttributes> getAnnotationAttributes(Method method, Class<? extends Annotation> annoClass, boolean searchOnClass){ AnnotationAttributes attrs = null; if(searchOnClass){ attrs = AnnotatedElementUtils.getMergedAnnotationAttributes(method, annoClass); if(attrs==null){ Class<?> clazz = method.getDeclaringClass(); attrs = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, annoClass); } }else{ attrs = AnnotatedElementUtils.getMergedAnnotationAttributes(method, annoClass); } return Optional.ofNullable(attrs); } public static Optional<AnnotationAttributes> getAnnotationAttributes(Method method, Class<? extends Annotation> annoClass){ return getAnnotationAttributes(method, annoClass, false); } /*** * * @author wayshall * @param applicationContext * @param value * @return */ public static String resolvePlaceholders(Object applicationContext, String value){ // return resolvePlaceholders(applicationContext, value, true); String resolvedValue = resolvePlaceholders(applicationContext, value, false); if (DOLOR.isExpresstion(resolvedValue)){ String convertedName = StringUtils.convertWithSeperator(resolvedValue, "-"); if (value.equals(convertedName)) { throw new BaseException("can not resolve placeholders value: " + value + ", resovled value: " + resolvedValue); } resolvedValue = resolvePlaceholders(applicationContext, convertedName, false); if (DOLOR.isExpresstion(resolvedValue)){ throw new BaseException("can not resolve placeholders value: " + value + ", resovled value: " + resolvedValue); } } return resolvedValue; } public static String resolvePlaceholders(Object applicationContext, String value, boolean throwIfNotResolved){ String newValue = value; if (StringUtils.hasText(value) && DOLOR.isExpresstion(value)){ if (applicationContext instanceof ConfigurableApplicationContext){ ConfigurableApplicationContext appcontext = (ConfigurableApplicationContext)applicationContext; newValue = appcontext.getEnvironment().resolvePlaceholders(value); } else if (applicationContext instanceof PropertyResolver){ PropertyResolver env = (PropertyResolver)applicationContext; newValue = env.resolvePlaceholders(value); } if (DOLOR.isExpresstion(newValue) && throwIfNotResolved){ throw new BaseException("can not resolve placeholders value: " + value + ", resovled value: " + newValue); } } return newValue; } public static <T> T toBean(Map<String, ?> propValues, Class<T> beanClass){ return MAP_TO_BEAN.toBean(propValues, beanClass); } public static MapToBeanConvertor getMapToBean() { return MAP_TO_BEAN; } public static String readClassPathFile(String path){ return readClassPathFile(path, FileUtils.DEFAULT_CHARSET); } public static String readClassPathFile(String path, String charset){ Resource res = classpath(path); try { return IOUtils.toString(res.getInputStream(), charset); } catch (IOException e) { throw new BaseException("read classpath file error: " + path); } } public static String readMultipartFile(MultipartFile multipartFile){ return readMultipartFile(multipartFile, FileUtils.DEFAULT_CHARSET); } public static String readMultipartFile(MultipartFile multipartFile, String charset){ try { return IOUtils.toString(multipartFile.getInputStream(), charset); } catch (IOException e) { throw new BaseException("read classpath file error: " + multipartFile.getOriginalFilename()); } } public static InputStream getInputStream(Resource resource){ try { return resource.getInputStream(); } catch (IOException e) { throw new BaseException("get InputStream error: " + resource.getFilename()); } } public static BeanToMapConvertor getBeanToMapConvertor(String... excludeProperties){ List<String> excludes = Lists.newArrayList(); excludes.addAll(Arrays.asList(excludeProperties)); BeanToMapConvertor convertor = BeanToMapBuilder.newBuilder() .ignoreNull() .excludeProperties(excludes.toArray(new String[0])) .enableFieldNameAnnotation() .build(); return convertor; } public static Set<Method> selectMethodsByParameterTypes(Class<?> targetClass, String targetMethod, Method sourceMethod) { Set<Method> methods = MethodIntrospector.selectMethods(targetClass, (MethodFilter)method -> { return method.getName().equals(targetMethod) && method.getParameterCount()==sourceMethod.getParameterCount() && Objects.deepEquals(method.getParameterTypes(), sourceMethod.getParameterTypes()); }); return methods; } }