Spring core源码

  • ClassUtils.

getDefaultClassLoader : 获取默认类加载器
forName :初始化类
resolveClassName 和forName只有处理异常的差别
resolvePrimitiveClassName 处理int等原始几个类
isPresent 是否能初始化该类
getUserClass :获取class,处理了 CGLIB_CLASS_SEPARATOR 的类
isCacheSafe :
getShortName : 根据类的完整名获取短名称 java.lang.String --> String 处理了CGLIB_CLASS_SEPARATOR,不会处理开头字母
getShortNameAsProperty : 根据类得到名称,并且会转化成峰坨格式 ,小写字母开头
getClassFileName: 得到有.class文件名称
getPackageName : 获取类的包名,没有类名
getQualifiedName : 获取完整的类名 java.lang.Double[]
getQualifiedMethodName : 完整的方法名
getDescriptiveType : 类签名信息,一般返回完整类名 com.sun.proxy.$Proxy4 implementing com.bydbl.proxy.staticmodel.UserService
matchesTypeName:类是否匹配名称
getConstructorIfAvailable:返回构造器,没有合适的返回空
hasMethod : 是否有方法
getMethod : 查找方法,没找到会报错 IllegalStateException
getMethodIfAvailable :返回方法
getMethodCountForName : 递归返回指定方法名出现的总数,覆写
hasAtLeastOneMethodWithName: 
getMostSpecificMethod :获取最适合的方法
getStaticMethod : 
isPrimitiveWrapper : 是否是基础类型的包装类
isAssignable: 是否是签名,是否为其子类,处理了基础类型
isAssignableValue : 和isAssignable差不多,这个传入的是Object,参数不一样
convertResourcePathToClassName: / --> .
convertClassNameToResourcePath : . --> /
addResourcePathToPackagePath  :
classPackageAsResourcePath: . -->
classNamesToString: 多个类名称的数组格式,以逗号分隔
toClassArray : 顾名思义
getAllInterfaces : 和getAllInterfacesForClass,getAllInterfacesAsSet 一样,就是多了个判空报错
getAllInterfacesForClassAsSet : 递归获取所有的接口
ClassUtils.createCompositeInterface(NaiveWaiter.class.getInterfaces(),ClassUtils.getDefaultClassLoader()) 创建接口的代理对象
determineCommonAncestor : 找到共同的祖先,继承关系
isCglibProxyClass: -->isCglibProxyClassName , 根据是否包含 CGLIB_CLASS_SEPARATOR 标识来判断
  • IdGenerator

其有3个实现类,SimpleIdGenerator ,JdkIdGenerator,AlternativeJdkIdGenerator

        IdGenerator idGenerator = new SimpleIdGenerator();
        for(int i =0 ;i<500;i++) {
            System.out.println(idGenerator.generateId().toString());
        }
输出:
00000000-0000-0000-0000-000000000001
00000000-0000-0000-0000-000000000002
00000000-0000-0000-0000-000000000003
00000000-0000-0000-0000-000000000004

        System.out.println("------------jdk---------");

        idGenerator = new JdkIdGenerator();
        for(int i =0 ;i<5;i++) {
            System.out.println(idGenerator.generateId().toString());
        }
输出:
00d1ca6a-a5aa-40a0-8fef-2b138e3d3634
9466039f-bbfb-480b-bd06-0a50b4df1889

        System.out.println("-----------alter---------");
        idGenerator = new AlternativeJdkIdGenerator();
        for(int i =0;i<5;i++) {
            System.out.println(idGenerator.generateId().toString());
        }
输出:
dd57c906-7ea5-015c-8a8a-14ed117e5710
c562d92d-f035-6f74-db40-b284148e4c7f
  • CollectionUtils:

arrayToList :参数是Object,传入数组,数组转List
mergeArrayIntoCollection : 数组合并到List,参数是Object,传入数组
mergePropertiesIntoMap : Properties 合并到Map
contains :是否包含,用equal比较
containsInstance : 是否包含,用== 比较,比较实例
containsAny : 第一个参考是否包含后一个参数中的任何一个
findFirstMatch :找到第一个参数包含第二个参数的第一个匹配对象
findValueOfType : 在一个集合中,包含各种类的集合,里面找到指定的类型
hasUniqueObject : 判断给定的集合是否为只包含一个值
findCommonElementType : 有任何一个不同类型就返回空,全部相同就返回对象类型,hasUniqueObject 是用== 比较,这个是用getClass比较
toArray : 转数组,可以是子类的集合转父类的数组
toIterator :
toMultiValueMap :  Map> 转 MultiValueMap
unmodifiableMultiValueMap : MultiValueMap 变成线程安全的 MultiValueMap
  • ConcurrencyThrottleSupport:

控制并发,可见 ConcurrencyThrottleInterceptor

    public ConcurrencyThrottleInterceptor() {
                //设置并发数
        setConcurrencyLimit(1);
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
              //进入前拿锁,数量加1
        beforeAccess();
        try {
            return methodInvocation.proceed();
        }
        finally {
                        //退出后释放,数量减1
            afterAccess();
        }
    }
  • ConcurrentReferenceHashMap

并发Hash Map,其键和值可以是弱引用或者软引用。
在JVM回收时会比硬引用更早回收
http://yuhuiblog6338999322098842.iteye.com/blog/2375746

  • DefaultPropertiesPersister

属性Properties的持久化,可以转成XML

        Properties p = new Properties();
        p.load(Files.newInputStream(Paths.get(fileName)));
        DefaultPropertiesPersister pp = new DefaultPropertiesPersister();
        pp.storeToXml(p,Files.newOutputStream(Paths.get(outXml)),"备注信息");

结果如下:



备注信息
"用户UUID"
8093
100
用户信息描述
dev: I'm living in ${home.province} ${home.city}.

ZheJiang
50

也可以读取已经生成的XML到properties

    @Test
    public void loadFromXml() throws IOException {
        DefaultPropertiesPersister pp = new DefaultPropertiesPersister();
        Properties p = new Properties();
        pp.loadFromXml(p,Files.newInputStream(Paths.get(outXml)));
        System.out.println(p);
    }
  • DigestUtils 数字签名 MD5

    @Test
    public void md5Digest() throws UnsupportedEncodingException {
        String value = "123";
        System.out.println(new String(DigestUtils.md5Digest(value.getBytes("utf-8"))));// ,�b�Y�[�K��-#Kp
        System.out.println(DigestUtils.md5DigestAsHex(value.getBytes("utf-8")));//202cb962ac59075b964b07152d234b70
    }
  • FileCopyUtils

复制文件的方法,各种复制...
和 commons-io的IOUtil差不多,但是这个只有复制功能,commons-io的IOUtils和FileUtils功能

  • FileSystemUtils :复制或删除文件(文件夹)操作,递归
  • LinkedCaseInsensitiveMap : 里面存的是一些大小写的key,但是get 和remove的时候可以不区分大小写
  • LinkedMultiValueMap : 线程不安全,实现了MultiValueMap数据结构,Map>
  • MethodInvoker:方法调用,静态方法也可以反射调用
    @Test
    public void invoker() throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
        MethodInvoker methodInvoker = new MethodInvoker();
        methodInvoker.setTargetClass(User.class);
        methodInvoker.setStaticMethod("com.bydbl.proxy.util.User.hello");
        methodInvoker.prepare();
        Object o = methodInvoker.invoke();
    }
package com.bydbl.proxy.util;

public class User {

    public void hi() {
        System.out.println("hi...");
    }

    public static void hello() {
        System.out.println("hello...");
    }
}
  • MimeType :处理HTTP的Mime类型

MimeTypeUtils

public static final MimeType X_JAVA_OBJECT = MimeType.valueOf("application/x-java-object")
private static final MimeType[] DEFAULT_SMILE_MIME_TYPES = new MimeType[] {
            new MimeType("application", "x-jackson-smile", StandardCharsets.UTF_8),
            new MimeType("application", "*+x-jackson-smile", StandardCharsets.UTF_8)};
  • NumberUtils

convertNumberToTargetClass : 将数字类型转换成目标类
parseNumber:将字符串转换成目标类型的数字,重载了两个方法,可以指定 NumberFormat

    @Test
    public void convertNumberToTargetClass() {
        BigDecimal b = NumberUtils.convertNumberToTargetClass(11111111111111111111111D, BigDecimal.class);
        System.out.println(b);
        BigDecimal decimal = NumberUtils.parseNumber("1111111111111111111111111", BigDecimal.class);
        System.out.println(decimal);
        decimal = NumberUtils.parseNumber("999,999,999", BigDecimal.class, NumberFormat.getInstance());
        System.out.println(decimal);

    }
  • PathMatcher

AntPathMatcher
extractUriTemplateVariables --> 转换成我们需要的Map

        String path = "/hotels/{hotel}";
        String pattern = "/hotels/1";
        PathMatcher pm = new AntPathMatcher();
        Map map = pm.extractUriTemplateVariables(path,pattern );
        System.out.println(map.toString());//输出:{hotel=1}
  • PatternMatchUtils

simpleMatch

  • PropertyPlaceholderHelper

将给定的模板替换掉,一般处理我们的属性文件的占位符

        Properties p = new Properties();
        p.put("name","aaaaa");
        p.put("age","23");
        p.put("address","china");
        PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${","}");
        System.out.println(helper.replacePlaceholders("${name}", p)); //aaaaa
        System.out.println(helper.replacePlaceholders("aaa ${name} bbb=${age} ccc = ${address}",p)); //aaa aaaaa bbb=23 ccc = china
        helper = new PropertyPlaceholderHelper("{","}");
        System.out.println(helper.replacePlaceholders("${name}", p));//$aaaaa

  • ReflectionUtils

有关反射的优先从此类中找方法,很多实用的,举一个小例子

findField :查找属性
    @Test
    public void setField() {
        User user = new User();
        user.setName("aaa");
        user.setAge(18);
        user.setBirth(new Date());

        Field field = ReflectionUtils.findField(User.class, "birth");
        ReflectionUtils.makeAccessible(field);
        Date birth = (Date)ReflectionUtils.getField(field, user);
        System.out.println(birth);
    }
  • ResourceUtils

处理了classpath:file,war,jar,file,zip等路径的工具类

    @Test
    public void getFile() throws FileNotFoundException {
        String location = "classpath:application.properties";
        //输出:D:\mytest\proxy\target\classes\application.properties
        System.out.println(ResourceUtils.getFile(location).getPath());
    }
  • InstanceComparator 用法实例

/**
 * FileName :InstanceComparatorTest
 * Author :zengzhijun
 * Date : 2018/5/21 10:58
 * Description:
 */
package org.springframework.util.comparator;

import org.aspectj.lang.annotation.*;
import org.junit.Test;
import org.springframework.core.convert.converter.ConvertingComparator;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * 
 * 下例先按 输入到 InstanceComparator 的先后顺序排队再根据方法名称排序
 * 因为要获取方法的注解,所以要用 ConvertingComparator 先转换到对应的注解
 * 参考 ReflectiveAspectJAdvisorFactory 内的方法
 *
 * @author : zengzhijun
 * @date : 2018/5/21 11:25
 **/
public class InstanceComparatorTest {


    private static final Comparator METHOD_COMPARATOR;

    static {
        Comparator adviceKindComparator =  new ConvertingComparator<>(
                new InstanceComparator<>(
                        Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                 method -> {
                    Annotation[] annotations = method.getDeclaredAnnotations();
                    return annotations[0];
                });
        Comparator methodNameComparator = new ConvertingComparator<>(Method::getName);
        METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
    }

    @Test
    public void comparate() {
        Method[] methods = ComparatorService.class.getDeclaredMethods();
        List methodList =  Arrays.asList(methods);
        methodList.sort(METHOD_COMPARATOR);
        methodList.stream().map(Method::getName).forEach(System.out::println);
    }

    class ComparatorService{

        @Around("around")
        public void around() {

        }

        @Around("bround")
        public void bround() {

        }

        @AfterThrowing
        public void afterThrowing() {

        }

        @AfterReturning
        public void afterReturning() {

        }

        @Before("before")
        public void before() {

        }


    }
}

  • AnnotationBeanUtils.copyPropertiesToBean
/**
 * FileName :AnnotationBeanUtilsTest
 * Author :zengzhijun
 * Date : 2018/5/21 14:35
 * Description:
 */
package org.springframework.beans.annotation;

import org.aspectj.lang.annotation.Before;
import org.junit.Test;
import org.springframework.core.annotation.AnnotationUtils;


/**
 * 
 * AnnotationBeanUtils : 将一个注解的信息对应到一个实体类的属性上
 * 本例展示将某一个方法上的注解信息转换到一个实体类上
 * 另: AnnotationBeanUtils 支持传入一个 StringValueResolver 和 excludedProperties 两个参数
 * 这样可以做更多处理
 * 
 * @author : zengzhijun
 * @date : 2018/5/21 14:45
 **/
public class AnnotationBeanUtilsTest {

    @Test
    public void copyPropertiesToBean() throws NoSuchMethodException {
        ServiceA serviceA = new ServiceA();
        Before annotation = AnnotationUtils.findAnnotation(ServiceA.class.getMethod("before"), Before.class);

        BeforeAttribute ba = new BeforeAttribute();
        AnnotationBeanUtils.copyPropertiesToBean(annotation,ba);
        System.out.println(ba);
    }

    class ServiceA {
        @Before(value = "aaa",argNames = "args")
        public void before() {

        }
    }
    class ServiceB {
        @Before(value = "bbb",argNames = "argsBBB")
        public void before() {

        }
    }
    class BeforeAttribute{
        private String value;
        private String argNames;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getArgNames() {
            return argNames;
        }

        public void setArgNames(String argNames) {
            this.argNames = argNames;
        }

        @Override
        public String toString() {
            return "BeforeAttribute{" +
                    "value='" + value + '\'' +
                    ", args='" + argNames + '\'' +
                    '}';
        }
    }
}

  • BeanUtils
/*
 * FileName :BeanUtilsTest
 * Author :zengzhijun
 * Date : 2018/5/21 14:54
 * Description:
 */
package org.springframework.beans;

import org.junit.Test;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Date;

public class BeanUtilsTest {

    /**
     *初始化类,Spring5 考虑到了 Kotlin
     **/
    @Test
    public void instantiateClass() throws NoSuchMethodException {
        PropertyValue propertyValue = BeanUtils.instantiateClass(PropertyValue.class.getConstructor(String.class, Object.class),"name","aaa");
        propertyValue.setAttribute("attr1","value1");
        System.out.println(propertyValue);
    }

    @Test
    public void instantiateClass1() throws ClassNotFoundException {
        String className = Person.class.getCanonicalName();
        Class clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
        Person person = BeanUtils.instantiateClass(clazz, Person.class);
        person.setAge(18);
        person.setName("name");
        System.out.println(person);
    }

    @Test
    public void findMethod() {
        //findMethod 不会递归查找父类
        Method sing = BeanUtils.findMethod(SuperMan.class, "fly");
        //会递归查找方法
        Method sing1 = BeanUtils.findDeclaredMethod(SuperMan.class, "sing");
        System.out.println(sing);
        System.out.println(sing1);

        //找到参数最小的同名方法,相当实用
        Method fly = BeanUtils.findDeclaredMethodWithMinimalParameters(SuperMan.class, "fly");
        SuperMan superMan = new SuperMan();

        ReflectionUtils.invokeMethod(fly, superMan);
    }

    @Test
    public void resolveSignature() {
        //methodName[([arg_list])
        //找到一个参数为空的方法
        Method exactlyFly = BeanUtils.resolveSignature("fly()", SuperMan.class);
        System.out.println(exactlyFly);
        //找到一个方法名为play的,参数最小的会返回
        Method play = BeanUtils.resolveSignature("play", SuperMan.class);
        System.out.println(play);
        //找到一个参数名为指定类型(完整的类型名称)的指定方法
        Method fly1 = BeanUtils.resolveSignature("fly(java.lang.String)", SuperMan.class);
        System.out.println(fly1);

        Method fly2 = BeanUtils.resolveSignature("fly(java.lang.String,java.lang.String)", SuperMan.class);
        System.out.println(fly2);

    }

    @Test
    public void getPropertyDescriptors() {
        //获取类的 getter 和 setter 方法,神器啊.
        PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(SuperMan.class);
        for (PropertyDescriptor descriptor : descriptors) {
            Method readMethod = descriptor.getReadMethod();
            Method writeMethod = descriptor.getWriteMethod();
            if (readMethod == null) {
                System.out.println("ignore readMethod : " + descriptor.getName());
                continue;
            }
            if (writeMethod == null) {
                System.out.println("ignore writeMethod : " + descriptor.getName());
                continue;
            }
            System.out.println("readMethod Name: " + readMethod.getName());
            System.out.println("writeMethod Name: " + writeMethod.getName());
        }
    }


    @Test
    public void findPropertyType() {
        //获取类中的属性的类型值
        Class age = BeanUtils.findPropertyType("age", Person.class);
        System.out.println(age);
    }

    @Test
    public void copyProperties() {
        //拷贝属性,最常用的方法
        SuperMan superMan = new SuperMan();
        superMan.setBirthday(new Date());
        superMan.setAge(18);
        superMan.setName("superman");

        SuperMan cloneMan = new SuperMan();
        //匹配上的属性全部复制
        BeanUtils.copyProperties(superMan,cloneMan);
        System.out.println(cloneMan);
        cloneMan = new SuperMan();
        //忽略 age 属性
        BeanUtils.copyProperties(superMan,cloneMan,"age");
        System.out.println(cloneMan);
        cloneMan = new SuperMan();
        //只复制 Person 里面的属性
        BeanUtils.copyProperties(superMan,cloneMan,Person.class);
        System.out.println(cloneMan);
    }
}

  • PropertyAccessorUtils

    @Test
    public void getPropertyName() {
        //输出:person
        System.out.println(PropertyAccessorUtils.getPropertyName("person[1]"));
        //是否是数组或者嵌套的属性格式
        System.out.println(PropertyAccessorUtils.isNestedOrIndexedProperty("person[1]"));
        System.out.println(PropertyAccessorUtils.isNestedOrIndexedProperty("person.age"));

        System.out.println(PropertyAccessorUtils.canonicalPropertyName("Asd_Wer"));
        System.out.println(PropertyAccessorUtils.canonicalPropertyName("asd_wer"));
        System.out.println(PropertyAccessorUtils.canonicalPropertyName("asdWer"));
        //输出:map[key]
        System.out.println(PropertyAccessorUtils.canonicalPropertyName("map[\"key\"]"));
        //true
        //true
        //Asd_Wer
        //asd_wer
        //asdWer
        //map[key]
    }

你可能感兴趣的:(Spring core源码)