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 机制吗?

posted @   懂得了才能做一些改变  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示