• Ctrip Apollo源码阅读


    1、切点的选择

      // 切点的定义
      @Pointcut("execution(public * org.spring.liong.Repository+.*(..))")
      public void anyRepository(){
      
      }
      // 切点的使用
      @Aroud("anyRepository")
      public Object invoke(ProceedingJointPoint point) {
      }
    

    aspectJ技术不常用,但是非常好用。告诉spring创建一个切面对象,它就可以工作了。

    假设我们引入了相应的包,会不会给我们自己的对象,生产相应的注解呢?这个就要看切点的选择了,所以限定包,可以防止滥用。

    切点定义的几种样式:AspectJ——切入点语法(1)之捕获方法上的连接点)

    2、注解的使用

    ​ 注解是jdk自带的功能,能通过反射获取其注解。

    
    package com.yk.annotation;
    
    import java.lang.annotation.*;
    
    @Documented
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Inherited
    @Retention(RetentionPolicy.SOURCE)
    public @interface MyAnnotation {
        String value() default "hello";
    
        String message() default "aaa";
    
    }
    
    

    ​ aspectJ也能通过注解,建立切点。同时我们也可以扫描全包

    3、Spring BeanUtils的使用

    ​ BeanUtil主要用于对象属性的复制,但是,它会把目标对象的null值也copy过来,这可能是我们不想要的。这时需要将null属性剔除。

    //忽略null值
    public static String[] getNullpropertyName(Object source) {
        //使用BeanWrapper封装传入的类
        BeanWrapper beanWrapper = new BeanWrapperImpl(source);
        //获取bean类所有的属性定义
        PropertyDescriptor[] pds = beanWrapper.getPropertyDescriptor();
        Set<String> emptyNames = new HashSet<>();
        for(PropertyDescriptor pd : pds) {
            //获取属性值
            Object beanValue = beanWrapper.getPropertyValue(pd.getName());
            if(beanValue == null) 
                empryNames.add(pd.getName());
        }
        String [] results = new String[emptyNames.size()];
        return emptyNames.toArray(results);
    } 
    

    BeanWrapper在get/set属性时,非常好用

    Spring源码系列:BeanWrapper

    4、Class.forName的使用

    public DataSource datasource() throws Exception{
    		Class clazz = Class.forName("com.ctrip.datasource.configure.DalDataSourceFactory");
    		Object obj = class.newInstance();
      	// 反射获取方法
      	Method method = clazz.getMethod("createDataSource",String.class,String.class);
    		DataSource ds = (DataSource)method.invoke(obj,this.settings.getTitanDbname(),this.settings.getTitanUrl());
      	return ds;
    }
    

    此处为什么使用forName加载,而不是ClassLoader,原因是Class.forName()在加载com.mysql.jdbc.Driver时,会执行静态代码块,向DriverManager注册自己

    在Java的反射中,Class.forName和ClassLoader的区别

    jdbc破坏双亲委派机制,是否破坏解析

    关于Class.forName是否破坏了双亲委派模型,这个还得商量。关键点估计是Driver类的加载时机,如果我们先使用Class.forName加载了,那在DriverMangeer就不用加载了。否则就会加载,并且使用ThreadContextClassLoader,就产生了破坏。

    5、Environment变量读取

    ​ 使用了Spirng提供的接口,其核心代码是

    
    MapProperteSource的类的使用
    RefreshablePropertySource source = new RefresPropertySource();
    this.environment.getPropertySources().addLast(souce);
    

    ​ 主要是ConfigureableEnvironment的使用

    6、java语言的spi机制

    什么是spi呢?好像我们也很少用到

    SPI ( Service Provider Interface),是一种服务发现机制。
    SPI 的本质是将接口的实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载对应接口的实现类。这样就可以在运行时,获取接口的实现类。

    与 JDK SPI 类似, 相对于 Java 的 SPI 的优势在于:
    Spring SPI 指定配置文件为 classpath 下的 META-INF/spring.factories,所有的拓展点配置放到一个文件中。
    配置文件内容为 key-value 类型,key 为接口的全限定名, value 为 实现类的全限定名,可以为多个

    ​ 所以说,有了这个技术,在springboot中,使用redis,就像使用jdbc一样丝滑

    你知道(Java 、Spring、Dubbo) SPI 机制吗?

  • 相关阅读:
    vue3的组合式API究竟是什么
    [COI2007] Patrik 音乐会的等待
    ASP.NET项目中使用FLEX4开发的应用 小记
    DataFormatString的格式 GridView数据常用格式化类型
    反应器Reactor和主动器Proactor的区别
    《深入理解JVM》笔记 第1章 Java发展史
    Nginx中的设计模式
    软考架构师教程笔记(二)计算机与网络基础
    《亿级流量》关于高可用和高并发的思维导图
    《深入理解JVM》笔记 第3章 GC
  • 原文地址:https://www.cnblogs.com/Robin008/p/16306926.html
Copyright © 2020-2023  润新知