jq获取当前li里的属性值_Spring注解里的那些骚操作

Spring 生态

384d424180c3d262e2387993c93de200.png

    Spring注解

    Spring认为所有的组件都应该放在ioc容器中,组件之间的关系通过容器依赖注入,而注解就是为了完成容器的注册,管理。

1727b064995afba6e18b3ebe488408f7.png

如图:当类上标识ConditionalOnBean,但是类又实现了BeanPostProcessor,那么此时的bean初始化有没有冲突呢?

1-ConditionalOnBean的功能:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean,也就是下面的方法想要获取实例bean,需要先实例化

2-BeanPostProcessor:相当于切面,在所有bean初始化之前执行,我们看一下执行顺序

AnnotationConfigApplicationContext(创建容器)->refresh   ->finishBeanFactoryInitialization      ->preInstantiateSingletons        ->getBean         ->doGetBean           ->createBean              ->doCreateBean                ->  this.populateBean(beanName, mbd, instanceWrapper);(类属性赋值)                    this.initializeBean(beanName, exposedObject, mbd);                    (BeanPostProcessor postProcessBeforeInstantiation和postProcessAfterInstantiation执行

那么此时的bean有没有被初始化呢?看起来是有冲突的,但是条件注解的解析一定发生在spring ioc的bean definition阶段,如何快速证明有没有冲突只需要构造器初始化一下,看一下当前的bean有没有被注入,当然也存在懒加载,多实例等情况,没有注册,这是后话了,看一下bean definition的入口

ConfigurationClassPostProcessor

/**   * Derive further bean definitions from the configuration classes in the registry.   */   派生bean的定义  @Override  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {    int registryId = System.identityHashCode(registry);    if (this.registriesPostProcessed.contains(registryId)) {      throw new IllegalStateException(          "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);    }    if (this.factoriesPostProcessed.contains(registryId)) {      throw new IllegalStateException(          "postProcessBeanFactory already called on this post-processor against " + registry);    }    this.registriesPostProcessed.add(registryId);     bean定义入口  ↓    processConfigBeanDefinitions(registry);  }

processConfigBeanDefinitions

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {......// Read the model and create bean definitions based on its content 读取实例并且创建bean 在上下文           if (this.reader == null) {        this.reader = new ConfigurationClassBeanDefinitionReader(            registry, this.sourceExtractor, this.resourceLoader, this.environment,            this.importBeanNameGenerator, parser.getImportRegistry());      }      this.reader.loadBeanDefinitions(configClasses);      alreadyParsed.addAll(configClasses);}

loadBeanDefinitions

/**   * Read {@code configurationModel}, registering bean definitions   * with the registry based on its contents.   */   根据内容注册bean   public void loadBeanDefinitions(Set configurationModel) {    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();    for (ConfigurationClass configClass : configurationModel) {      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);    }  }
/**   * Read a particular {@link ConfigurationClass}, registering bean definitions   * for the class itself and all of its {@link Bean} methods.   */  private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,      TrackedConditionEvaluator trackedConditionEvaluator) {    if (trackedConditionEvaluator.shouldSkip(configClass)) {      String beanName = configClass.getBeanName();      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {        this.registry.removeBeanDefinition(beanName);      }      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());      return;    }    if (configClass.isImported()) {      registerBeanDefinitionForImportedConfigurationClass(configClass);    }    for (BeanMethod beanMethod : configClass.getBeanMethods()) {      loadBeanDefinitionsForBeanMethod(beanMethod);    }    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());  }

if (configClass.isImported())当解析完注解解析时,beanDefinition已经被同步,

也就是ConditionalOnBean已经被同步,如果此时构造器初始化是不会报错的。

实际应用场景中在定义DataSourcePool时,加载外部配置类,此时的注解能够解析加载那个dataSource,但应用场景不多。

牛X哄哄的ExtensionLoader

Dubbo的SPIcom.alibaba.dubbo.common.extension.SPI

/** * Dubbo使用的扩展点获取。<p> * <ul> * <li>自动注入关联扩展点。li> * <li>自动Wrap上扩展点的Wrap类。li> * <li>缺省获得的的扩展点是一个Adaptive Instance。 * ul> *  * @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">JDK5.0的自动发现机制实现a> *  * @author william.liangf * @author ding.lid * * @see com.alibaba.dubbo.common.extension.SPI * @see com.alibaba.dubbo.common.extension.Adaptive * @see com.alibaba.dubbo.common.extension.Activate */

dubbo的服务发现机制,JDK也有自己的服务发现机制,SPI可看做是其实现,但布道的时候,对ExtensionLoader十分推崇,生成其可自动生成字节码文件,无须jvm编译,但其实调用的是非jdk的编译包,

private Class> createAdaptiveExtensionClass() {        String code = createAdaptiveExtensionClassCode();        ClassLoader classLoader = findClassLoader();        com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();        return compiler.compile(code, classLoader);    }

当然,重要的还是开头类注释的注解@Adaptive注解标识类,还有个Active,另外这段代码好骚啊

private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();

用注解当类型?

         if (names != null && names.length > 0) {        Activate activate = clazz.getAnnotation(Activate.class);        if (activate != null) {        cachedActivates.put(names[0], activate);        }                                      

其调用的Map的put方法

25982eb8c3da1444aa39fb0af696b22a.png

将指定值与此映射中的指定键相关联,在使用时用来获取已经加载的扩展点的name,好在大部分的dubbo注释是中文的,可联系上下文看到其作用

推荐阅读

dubbo源码分析 1 -- ExtensionLoader.getExtensionLoader

d39baa174d6fdfe5ee7168a5bf0a9fbc.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值