范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

ImportSelector与DeferredImportSelector的区别(spring4)

  欢迎访问我的 GitHub
  这里分类和汇总了欣宸的全部原创(含配套源码): https://github.com/zq2599/blog_demos  在使用 @Import 注解来注册 bean 的时候,Import 注解的值可以是 ImportSelector 或者 DeferredImportSelector 的实现类,spring 容器会实例化这个实现类,并执行其 selectImports 方法,那么问题来了: ImportSelector 和 DeferredImportSelector 的区别在哪里,我们自定义 Imort 逻辑的时候该选择哪个呢? 本文通过分析相关的 spring 源码来查找答案;  全文概览本文由以下几部分组成:  看官方文档;  分析 spring 源码中对这两个接口的处理;  实战验证;  看官方文档先看官方文档看起,我选择了 4.3.9 版本在线文档(这是个 Release 版),地址:https://docs.spring.io/spring/docs/4.3.19.RELEASE/javadoc-api/  原文:A variation of ImportSelector that runs after all @Configuration beans have been processed. This type of selector can be particularly useful when the selected imports are @Conditional.Implementations can also extend the Ordered interface or use the Order annotation to indicate a precedence against other DeferredImportSelectors.  我的理解:  DeferredImportSelector 是 ImportSelector 的一个扩展;  ImportSelector 实例的 selectImports 方法的执行时机,是在 @Configguration 注解中的其他逻辑被处理   之前   ,所谓的其他逻辑,包括对 @ImportResource、@Bean 这些注解的处理(注意,这里只是对 @Bean 修饰的方法的处理,并不是立即调用 @Bean 修饰的方法,这个区别很重要!);  DeferredImportSelector 实例的 selectImports 方法的执行时机,是在 @Configguration 注解中的其他逻辑被处理   完毕之后   ,所谓的其他逻辑,包括对 @ImportResource、@Bean 这些注解的处理;  DeferredImportSelector 的实现类可以用 Order 注解,或者实现 Ordered 接口来对 selectImports 的执行顺序排序;  分析 spring 源码中对这两个接口的处理接下来看看源码:  在 spring-framework-4.1.8.RELEASE 工程中找到类 ConfigurationClassParser.java,这里面有处理配置类的主要逻辑;  找到方法 parse(Set configCandidates):  public void parse(Set configCandidates) {     this.deferredImportSelectors = new LinkedList();     //检查每个bean的定义     for (BeanDefinitionHolder holder : configCandidates) {       BeanDefinition bd = holder.getBeanDefinition();       try {         if (bd instanceof AnnotatedBeanDefinition) {           //对于每个有注解的类,都执行方法parse(AnnotationMetadata metadata, String beanName)           parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());         }         else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {           parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());         }         else {           parse(bd.getBeanClassName(), holder.getBeanName());         }       }       catch (BeanDefinitionStoreException ex) {         throw ex;       }       catch (Exception ex) {         throw new BeanDefinitionStoreException(             "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);       }     }          //最后再处理DeferredImportSelector的实现类     processDeferredImportSelectors();   }
  复制代码由以上代码可以大致看出 DeferredImportSelector 的实现类被最后放在 processDeferredImportSelectors 方法中处理,那么前面的 parse(AnnotationMetadata metadata, String beanName)做了些什么呢?继续看;  展开方法 parse(AnnotationMetadata metadata, String beanName)里面,是执行 processConfigurationClass 方法;  再展开 processConfigurationClass 方法,看到核心逻辑是调用 doProcessConfigurationClass 方法,展开看看:  protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {     //为了聚焦Import相关处理,此处略去部分不相关代码,不在这里展示了     ...     ...     // 处理@Import注解     processImports(configClass, sourceClass, getImports(sourceClass), true);       // 处理@ImportResource注解     if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {       AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);       String[] resources = importResource.getStringArray("value");       Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");       for (String resource : resources) {         String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);         configClass.addImportedResource(resolvedResource, readerClass);       }     }       // 处理@Bean注解,注意是处理注解,不是执行@Bean修饰的方法     Set beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());     for (MethodMetadata methodMetadata : beanMethods) {       configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));     }       // 处理Configuration类的父类,外面在调用doProcessConfigurationClass方法的时有迭代处理,确保所有父类的注解都会被处理     if (sourceClass.getMetadata().hasSuperClass()) {       String superclass = sourceClass.getMetadata().getSuperClassName();       if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {         this.knownSuperclasses.put(superclass, configClass);         // Superclass found, return its annotation metadata and recurse         return sourceClass.getSuperClass();       }     }       // 再也没有父类了,返回null表示当前Configuration处理完毕     return null;   }
  复制代码根据上述代码分析,可以梳理出下图中的逻辑:
  现在需要再看看 processImports 和 processDeferredImportSelectors 这两个方法的具体代码;  先看 processImports 方法:  private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,       Collection importCandidates, boolean checkForCircularImports) throws IOException {       if (importCandidates.isEmpty()) {       return;     }       if (checkForCircularImports && this.importStack.contains(configClass)) {       this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));     }     else {       this.importStack.push(configClass);       try {         for (SourceClass candidate : importCandidates) {           //如果是ImportSelector接口的实现类,就在此处理           if (candidate.isAssignable(ImportSelector.class)) {             // Candidate class is an ImportSelector -> delegate to it to determine imports             Class<?> candidateClass = candidate.loadClass();             //实例化这些ImportSelector的实现类             ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);             //如果这实现类还实现了BeanFactoryAware、EnvironmentAware这些接口,就要先执行这些接口中声明的方法             invokeAwareMethods(selector);             //如果这个实现类也实现了DeferredImportSelector接口,就被加入到集合deferredImportSelectors中             if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {               this.deferredImportSelectors.add(                   new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));             }             else {               //注意,这一行是关键代码!!!执行实现类的selectImports方法               String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());               Collection importSourceClasses = asSourceClasses(importClassNames);               processImports(configClass, currentSourceClass, importSourceClasses, false);             }           }           //此处略去的和ImportSelector不相关的逻辑代码           ...           ...           ...         }       }       catch (BeanDefinitionStoreException ex) {         throw ex;       }       catch (Exception ex) {         throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +             configClass.getMetadata().getClassName() + "]", ex);       }       finally {         this.importStack.pop();       }     }   }
  复制代码以上代码有两个关键点:  第一、当前被处理的类,如果实现了 DeferredImportSelector 接口,就被加入到集合 deferredImportSelectors 中;  第二、当前被处理的类,如果没有实现 DeferredImportSelector 接口,但是实现了 ImportSelector 接口,就被执行 selectImports 方法;  接下来看看 processDeferredImportSelectors 方法的源码,提前推测应该是处理集合 deferredImportSelectors 中的所有类,这些类都实现了 DeferredImportSelector 接口:  private void processDeferredImportSelectors() {     List deferredImports = this.deferredImportSelectors;     this.deferredImportSelectors = null;     //按照Order注解或者Ordered接口进行排序     Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);       for (DeferredImportSelectorHolder deferredImport : deferredImports) {       ConfigurationClass configClass = deferredImport.getConfigurationClass();       try {         //此处是关键代码,执行DeferredImportSelector实现类的selectImports方法         String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());         processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);       }       catch (BeanDefinitionStoreException ex) {         throw ex;       }       catch (Exception ex) {         throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +             configClass.getMetadata().getClassName() + "]", ex);       }     }   }
  复制代码至此,源码分析完毕了,从代码可以很清晰的看出 ImportSelector 与 DeferredImportSelector 的区别,就是 selectImports 方法执行时机有差别,这个差别期间,spring 容器对此 Configguration 类做了些其他的逻辑:包括对 @ImportResource、@Bean 这些注解的处理(注意,这里只是对 @Bean 修饰的方法的处理,并不是立即调用 @Bean 修饰的方法,这个区别很重要!);  实战验证接下来到了实战验证的环节了,本次实战的内容是创建一个 springboot 工程,在里面自定义三个 ImportSelector 接口的实现类,如果您不想敲代码,也可以去 github 下载源码,地址和链接信息如下表所示:
  这个 git 项目中有多个文件夹,本章源码在文件夹 customizeimportselector 下,如下图红框所示:
  开始编码吧:  我们创建三个 ImportSelector 的实现类来检查其先后顺序,三个 Selector 类简介如下表,有两个是 DeferredImportSelector 的实现类,一个是 ImportSelector 的实现类,每个 Selector 负责向 spring 容器注册一种实例:
  基于 maven 创建 springboot 框架的 web 工程,pom.xml 内容如下:  <?xml version="1.0" encoding="UTF-8"?>      4.0.0       com.bolingcavalry     customizeimportselector     0.0.1-SNAPSHOT     jar       customizeimportselector     Demo project for Spring Boot                org.springframework.boot         spring-boot-starter-parent         1.5.9.RELEASE                               UTF-8         UTF-8         1.8                                  org.springframework.boot             spring-boot-starter-web                                 org.springframework.boot             spring-boot-starter-test             test                                                            org.springframework.boot                 spring-boot-maven-plugin                            
  复制代码创建三个接口 CustomizeService1、CustomizeService2、CustomizeService3,第一个源码如下,另外两个除了类名,其余部分一样:  package com.bolingcavalry.customizeimportselector.service;   public interface CustomizeService1 {     void execute(); }
  复制代码创建三个类,分别实现上面的三个接口,也是除了类名其余部分一样:  package com.bolingcavalry.customizeimportselector.service.impl;   import com.bolingcavalry.customizeimportselector.service.CustomizeService1;   public class CustomizeServiceImpl1 implements CustomizeService1 {       public CustomizeServiceImpl1() {         System.out.println("construct : " + this.getClass().getSimpleName());     }       @Override       public void execute() {         System.out.println("execute : " + this.getClass().getSimpleName());     } }
  复制代码创建 CustomizeImportSelector1:  package com.bolingcavalry.customizeimportselector.selector;   import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotationMetadata;   @Order(102) public class CustomizeImportSelector1 implements DeferredImportSelector {     @Override     public String[] selectImports(AnnotationMetadata annotationMetadata) {         System.out.println("selectImports : " + this.getClass().getSimpleName());         return new String[]{"com.bolingcavalry.customizeimportselector.service.impl.CustomizeServiceImpl1"};     } }
  复制代码创建 CustomizeImportSelector2:  package com.bolingcavalry.customizeimportselector.selector;   import org.springframework.context.annotation.DeferredImportSelector; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotationMetadata;   @Order(101) public class CustomizeImportSelector2 implements DeferredImportSelector {     @Override     public String[] selectImports(AnnotationMetadata annotationMetadata) {         System.out.println("selectImports : " + this.getClass().getSimpleName());         return new String[]{"com.bolingcavalry.customizeimportselector.service.impl.CustomizeServiceImpl2"};     } }
  复制代码创建 CustomizeImportSelector3,实现的是 ImportSelector 接口:  package com.bolingcavalry.customizeimportselector.selector;   import org.springframework.context.annotation.ImportSelector; import org.springframework.core.annotation.Order; import org.springframework.core.type.AnnotationMetadata;   public class CustomizeImportSelector3 implements ImportSelector {     @Override     public String[] selectImports(AnnotationMetadata annotationMetadata) {         System.out.println("selectImports : " + this.getClass().getSimpleName());         return new String[]{"com.bolingcavalry.customizeimportselector.service.impl.CustomizeServiceImpl3"};     } }
  复制代码创建配置类,将 CustomizeImportSelector1、CustomizeImportSelector2、CustomizeImportSelector3 全部用 Import 注解引入:  package com.bolingcavalry.customizeimportselector;   import com.bolingcavalry.customizeimportselector.selector.CustomizeImportSelector1; import com.bolingcavalry.customizeimportselector.selector.CustomizeImportSelector2; import com.bolingcavalry.customizeimportselector.selector.CustomizeImportSelector3; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import;   @Configuration @Import({CustomizeImportSelector1.class, CustomizeImportSelector2.class, CustomizeImportSelector3.class}) public class SysConfig { }
  复制代码创建启动类 CustomizeimportselectorApplication.java:  package com.bolingcavalry.customizeimportselector;   import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;   @SpringBootApplication public class CustomizeimportselectorApplication {       public static void main(String[] args) {         SpringApplication.run(CustomizeimportselectorApplication.class, args);     } }
  复制代码启动应用,可见输入信息如下:  2018-09-09 15:43:45.790  INFO 15364 --- [           main] c.b.c.CustomizeimportselectorApplication : Starting CustomizeimportselectorApplication on DESKTOP-82CCEBN with PID 15364 (D:githubblog_demoscustomizeimportselector	argetclasses started by 12167 in D:githubblog_demoscustomizeimportselector) 2018-09-09 15:43:45.791  INFO 15364 --- [           main] c.b.c.CustomizeimportselectorApplication : No active profile set, falling back to default profiles: default 2018-09-09 15:43:45.825  INFO 15364 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@641147d0: startup date [Sun Sep 09 15:43:45 GMT+08:00 2018]; root of context hierarchy selectImports : CustomizeImportSelector3 selectImports : CustomizeImportSelector2 selectImports : CustomizeImportSelector1 2018-09-09 15:43:46.425  INFO 15364 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2018-09-09 15:43:46.430  INFO 15364 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat] 2018-09-09 15:43:46.431  INFO 15364 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.23 2018-09-09 15:43:46.493  INFO 15364 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext 2018-09-09 15:43:46.493  INFO 15364 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 670 ms 2018-09-09 15:43:46.569  INFO 15364 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: "dispatcherServlet" to [/] 2018-09-09 15:43:46.572  INFO 15364 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: "characterEncodingFilter" to: [/*] 2018-09-09 15:43:46.572  INFO 15364 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: "hiddenHttpMethodFilter" to: [/*] 2018-09-09 15:43:46.572  INFO 15364 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: "httpPutFormContentFilter" to: [/*] 2018-09-09 15:43:46.572  INFO 15364 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: "requestContextFilter" to: [/*] construct : CustomizeServiceImpl1 construct : CustomizeServiceImpl2 construct : CustomizeServiceImpl3
  复制代码从上述信息可以看出:  首先、三个 selector 实现类的 selectImports 方法执行顺序符合预期:先执行 ImportSelector 实现类的,再执行 DeferredImportSelector 实现类的,并且 DeferredImportSelector 实现类的执行顺序会按照 Order 的设置   从小到大   执行;  其次、CustomizeServiceImpl1、CustomizeServiceImpl2、CustomizeServiceImpl3 的实例化顺序并未受到影响;  至此,ImportSelector 与 DeferredImportSelector 的区别已经分析和验证完毕,随着对 Configuration 初始化处理逻辑的深入了解,我们可以定制出更灵活强大的配置逻辑,以符合业务需求;  欢迎关注 InfoQ:程序员欣宸
  学习路上,你不孤单,欣宸原创一路相伴...

惠英红胡歌相差22岁同框似姐弟,追星不分年纪近日,惠英红和胡歌参加了阿玛尼2021秋冬系列高级定制时装秀。当天61岁的惠英红穿着深蓝色闪光长外套,爆炸头加红唇,性感又优雅。胡歌穿着蓝色毛衣搭配黑色外套,英气十足,39岁的他真ampampquot国民妹妹ampampquot张子枫5岁随母北漂,11岁赢胡歌夺奖,今成圈内团宠一张子枫有5个爸爸,每个都让她在成功的道路上更进一步。张子枫是河南省三门峡人,家境普通,亲生父亲是供电公司工人,母亲是商贸公司文员,后来辞职当家庭主妇。在家中她跟父亲关系最好,在北陈亚男和朱单伟的婚姻,终究是一场爱情买卖陈亚男朱单伟分居了!和我们预想的一样,这对不合适的年轻人终究要分开,只不过我们预期不到具体的分开理由!为什么说他们会分开呢?因为带有买卖性质的婚姻注定是不长久的!朱单伟,也就是大衣长相端方的女演员,我只服这4位!这气质90后小花根本比不了我们经常用美艳有灵气有气质来形容一个人的长相,却很少用端方来形容。其实端方的长相就是周正端正,感觉很大气沉稳的样子。有人用这个词语形容周涛,一袭红衣,满脸笑容,国泰民安的感觉也有很郭晶晶近照颜值开挂!穿白衬衣带老公高调亮相,照样不穿大牌太牛郭晶晶如今的衣品似乎越来越出色了,几次的私下穿搭,虽然依旧没有任何的大牌影子,但是满身的品质感和高级感可是十分的明显,而不久前,郭晶晶晒出了自己和霍启刚一起参观典亚艺博展览的照片,赵本山为什么不同意出狱后的胖丫复出?难道真不给她机会了吗?赵本山最早力捧的女徒弟就是胖丫了,但是因为卖假药葬送了自己的星途,被判刑3年的胖丫赵丹在今年2月份就刑满释放了,出狱半年多的胖丫一直没有登台演出,是赵本山惩戒犯了错误的赵丹还是另有欧弟晒视频为林志颖庆生!霍建华林俊杰出镜,四人容颜不见老10月16日,欧弟在社交平台晒出一条恶搞视频为林志颖庆生,配文28岁生日快乐不老男神!让我们一起赛车到老吧!照片中,欧弟霍建华林俊杰和林志颖四个人站成一排,互相搭着彼此的肩膀十分亲三部口碑炸裂的悬疑剧,豆瓣评分9分以上,哪一部是你的最爱?1暗算时隔十年,暗算这部谍战悬疑剧依旧深深地刻印在观众的脑海中,尤其是这部剧的经典人物柳云龙可谓是当时所有观众的男神,观众也把柳云龙称之为悬疑剧之父。这部剧分为三部分,分别是听风看舍得酒业的老酒只是故事讲故事讲不出品牌和美誉度,营收和利润也难以靠此维系文李廷祯郑慧先说三大结论1。舍得酒业(600702。SH)的1213万吨基酒,号称贮龄超长,是陶罐贮存的优质基酒,这是一个谎言。舍这世界有那么多人火了遇见是天意,拥有是幸运晚风中闪过几帧从前啊飞驰中旋转已不见了吗远光中走来你一身晴朗身旁那么多人可世界不声不响世界上的歌有很多,真正让人落泪,往往都是看似唱得漫不经心,但字字戳心。听莫文蔚的这首歌,总会在请寻找你内心珍视的坚持追求成功追求优秀追求完美的自己挣更多的钱。这些固然没错,但是这些值得抛却自己对于家人之间的情感。值得你连自己的身体都不顾吗?我常听到一句话我现在满脑子都是赚钱。先不说这本就极难,我
HWC冠军杯LOL手游赛事开启,千一率队全胜晋级八强,已成夺冠热门最近LOL手游在国内手游圈中的热度只增不减,作为英雄联盟的手游版本,它不仅吸引了很多LOL的忠实玩家,还有很多新手玩家来凑热闹,很快在一些直播平台涌现出不少LOL实力主播,虎牙千一LOL手游虎牙冠军杯诞生全能野王,他让人想起EDG打野JIEJIE英雄联盟手游上线至今也有一段时间了,背靠着英雄联盟这个超级IP,游戏热度一直是居高不下,相关职业赛事正在逐渐完善当中。近日,由虎牙直播举办的英雄联盟手游冠军杯正在火热进行当中,目前狼队太气人了!只拿KPL冠军还不够?队员Hurt和杰杰包揽KGL冠亚在KPL秋季赛开展的同时,次级联赛KGL也在激烈的进行之中,而且他们的进度要比KPL比赛还要快一些,已经结束了败者组决赛的争夺,还剩下最后的总决赛。巧合的是,这次KGL总决赛参与者比杨幂赵丽颖会挑老公,比李小璐忠于婚姻的霍思燕,是人生赢家在娱乐圈资本圈的版图中,霍思燕顶着七仙女的头衔的出现在中间偏上位置。七仙女里,七公主紫儿最向往朴素平凡的人间烟火。霍思燕也是七个里面最有观众缘的演员。在王牌七仙女怀旧节目里,就她没WTT夺冠还没完!孙颖莎或收更大惊喜,刘国梁该下定决心了大家好!欢迎来到大胡子体育吧!本期节目将和球迷朋友一起聊一聊WTT世界杯决赛,聊一聊女单冠军孙颖莎。我们知道,WTT世界杯决赛已经正式落幕了,中国乒团也是继东京奥运会以及世乒赛之后3消息!1。07亿签约将达成!曝湖人交易兰姆方案,步行者要重建大家好!我们今天来聊聊NBA,为大家分享几则NBA消息1。07亿签约将达成!曝湖人交易兰姆方案,步行者要重建。首先,1。07亿签约将达成!ESPN名记今天撰文发布报道,谈到了开拓者中超3家球队或弃赛,外援吼吴金贵我是来挣钱的,不是搞扶贫根据中超日历,中超联赛联赛第2阶段保级组争冠组赛事分别计划于12月12日在苏州广州两大赛区展开。和以往一样,每次到了开赛前期,总有不少球队会传出弃赛的消息,这一次,球员们可能要动真拿了能满血吃鸡的海克斯科技卓尔不群的最强阵容配置云顶S6这期介绍卓尔不群这个海克斯,这是一个非常牛掰的海克斯,吃鸡率很高,开局拿到金色以上卓尔不群就是把爽局。如果是一级卓尔不群就要拼运气了。九五卓尔不群介绍一下科技效果你的弈子们只要不具詹姆斯说湖人不需要改变阵容,是硬撑还是有底气?今天,湖人队训练之后,詹姆斯接受记者采访时说了一段话,大概意思是说他认为目前湖人的阵容不需要改变,他爱更衣室中的每一个队友,也认为佩林卡的工作很不错,期望湖人接下来的旅程。这段话说NASA激光通信演示设备和紫外线光子仪成功发射2021年12月7日星期二,美国联合发射联盟的阿特拉斯五号火箭从卡纳维拉尔角空军基地的41号航天发射场发射国防部的空间测试计划3(STP3)任务。该任务的空间测试计划卫星6(STPWTT世界杯新星崛起,三足鼎立现象将出现?刘国梁说出大实话现在是北京时间12月8日,昨天晚上的世界杯总决赛传来了好消息,樊振东对战张本智和,后者在比赛中不敌樊振东,被樊振东碾压成功获得了比赛的冠军。与此同时,女单方面也传来了好消息,孙颖莎