Springboot自动装配原理_自动装配原理

Springboot自动装配原理_自动装配原理springboot自动装配原理详解1)传统ssm整合redis的时候需要在xml的配置文件中进行大量的配置Bean我们在这里使用springboot来代替ssm的整合,只是通过xml的形式来整合redis第一步:加入配置<dependency><groupId>org.springframework.data</grou…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

springboot自动装配原理详解

1)传统ssm整合redis的时候 需要在xml的配置文件中 进行大量的配置Bean

我们在这里使用springboot来代替ssm的整合,只是通过xml的形式来整合redis

第一步:加入配置

<dependency>

          <groupId>org.springframework.data</groupId>

          <artifactId>spring-data-redis</artifactId>

          <version>2.0.9.RELEASE</version>

</dependency>

<dependency>

          <groupId>redis.clients</groupId>

         <artifactId>jedis</artifactId>

          <version>2.9.0</version>

</dependency>

第二步: 配置xml的bean的配置 

//配置连接池  

   <bean id=”poolConfig” class=”redis.clients.jedis.JedisPoolConfig”>   

      <property name=”minIdle” value=”10″></property>    

     <property name=”maxTotal” value=”20″></property>    

 </bean>        

  //配置连接工厂     <bean id=”jedisConnectionFactory” class=”org.springframework.data.redis.connection.jedis.JedisConnectionFactory”>         <property name=”hostName” value=”47.104.128.12″></property>         <property name=”password” value=”123456″></property>  

        <property name=”database” value=”0″></property>    

       <property name=”poolConfig” ref=”poolConfig”></property>    

 </bean>  

   //配置 redisTemplate 模版类    

 <bean id=”redisTemplate” class=”org.springframework.data.redis.core.RedisTemplate”>         <property name=”connectionFactory”  ref=”jedisConnectionFactory”/>    

     <!–如果不配置Serializer,那么存储的时候默认使用String,如果用User类型存储,那么会提示错误User can’t cast to String!  –>   

      <property name=”keySerializer”>             <bean class=”org.springframework.data.redis.serializer.StringRedisSerializer”/>   

      </property>         

    <property name=”valueSerializer”>             <bean class=”org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer”/>     

    </property>    

     <property name=”hashKeySerializer”>             <bean class=”org.springframework.data.redis.serializer.StringRedisSerializer”/>       

  </property>    

     <property name=”hashValueSerializer”>          <bean class=”org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer”/>     

    </property>

    </bean>

第三步:导入配置 

@ImportResource(locations = “classpath:beans.xml”)  此注解用于导入xml的配置文件

@SpringBootApplication

@ImportResource(locations = “classpath:beans.xml”)

@RestController public class TulingOpenAutoconfigPrincipleApplication {

          @Autowired

          private RedisTemplate redisTemplate;

          public static void main(String[] args) {

                 SpringApplication.run(TulingOpenAutoconfigPrincipleApplication.class, args);

          }

          @RequestMapping(“/testRedis”)

          public String testRedis() {

                 redisTemplate.opsForValue().set(“smlz”,”smlz”); return “OK”;

          }

 }

2)综上所述 我们发现,若整合redis的时候通过传统的整合,进行了大量的配置,那么我们来看下通过springboot自动装配整合的对比

导入依赖: 

<dependency>

          <groupId>org.springframework.boot</groupId>

          <artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

修改yml配置文件 

spring.redis.host=47.104.128.12

spring.redis.port=6379

spring.redis.password=123456

直接使用(下述代码可以不要配置,为了解决保存使用jdk的序列方式才配置的) 

@Bean

          public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)  {                                 RedisTemplate<Object, Object> template = new RedisTemplate<>();                                                                                     template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));                                                     template.setConnectionFactory(redisConnectionFactory); return template;

}​

3)传统整合和springboot自动装配 优劣势分析 

Springboot自动装配原理_自动装配原理

4)自动装配原理前的不得不说的几个注解

4.1)通过@Import注解来导入ImportSelector组件

①:写一个配置类在配置类上标注一个@Import的注解

@Configuration

@Import(value = {TulingSelector.class})

public class TulingConfig {

}​

②:在@Import注解的value值  写自己需要导入的组件 

       在selectImports方法中 就是你需要导入组件的全类名

public class TulingSelector implements ImportSelector {   

  @Override     

  public String[] selectImports(AnnotationMetadata annotationMetadata) {    

     return new String[]{“com.tuling.service.TulingServiceImpl“};  

   }

}

 核心代码:

@RestController

public class TulingController {     

    //自动注入 tulingServiceImpl   

  @Autowired   

  private TulingServiceImpl tulingServiceImpl;   

  @RequestMapping(“testTuling”)    

 public String testTuling() {   

      tulingServiceImpl.testService();       

      return “tulingOk”;   

  }

}

这里是没有标注其他注解提供给spring包扫描的

public class TulingServiceImpl {    

 public void testService() {   

      System.out.println(“我是通过importSelector导入进来的service”);     

   }

}

Springboot自动装配原理_自动装配原理 1.2)通过@Import导入ImportBeanDefinitionRegistrar 从而进来导入组件

Springboot自动装配原理_自动装配原理

 核心代码:

public class TulingImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {   

  @Override     public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, 

                                                                               BeanDefinitionRegistry beanDefinitionRegistry) {     

    //定义一个BeanDefinition

        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TulingDao.class);      

   //把自定义的bean定义导入到容器中    

     beanDefinitionRegistry.registerBeanDefinition(“tulingDao”,rootBeanDefinition);    

    }

}​

通过ImportSelector功能导入进来的

public class TulingServiceImpl {    

 @Autowired   

  private TulingDao tulingDao;     

public void testService() {      

   tulingDao.testTulingDao();         

System.out.println(“我是通过importSelector导入进来的service”);  

   }

}

通过ImportBeanDefinitionRegistar导入进来的

public class TulingDao {   

  public void testTulingDao() {       

  System.out.println(“我是通过ImportBeanDefinitionRegistrar导入进来tulingDao组件”);   

  }

}

测试结果:

Springboot自动装配原理_自动装配原理

 

1.3)spring底层条件装配的原理@Conditional

应用要求:比如我有二个组件,一个是TulingLog  一个是TulingAspect

而TulingLog 是依赖TulingAspect的 只有容器中有TulingAspect组件才会加载TulingLog

tulingLog组件  依赖TulingAspect组件

public class TulingLog {

}

tulingAspect组件

public class TulingAspect {

}

①:自定义条件组件条件 

public class TulingConditional implements Condition {  

   @Override     public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {   

      //容器中包含tulingAspect组件才返回Ture    

     if(conditionContext.getBeanFactory().containsBean(“tulingAspect”)){    

         return true;       

  }else{       

      return false;         }  

   }

}

                        ————————————-该情况下会加载二个组件————————————————-

@Bean   

  public TulingAspect tulingAspect() {     

    System.out.println(“TulingAspect组件自动装配到容器中”);     

    return new TulingAspect();     }        

       @Bean   

  @Conditional(value = TulingConditional.class)   

  public TulingLog tulingLog() {     

    System.out.println(“TulingLog组件自动装配到容器中”);    

     return new TulingLog();   

  }

                               ————————————-二个组件都不会被加载—————————————-

/*@Bean**/     

public TulingAspect tulingAspect() {      

   System.out.println(“TulingAspect组件自动装配到容器中”);   

      return new TulingAspect();  

   }             

  @Bean   

  @Conditional(value = TulingConditional.class)   

  public TulingLog tulingLog() {      

   System.out.println(“TulingLog组件自动装配到容器中”);    

     return new TulingLog();  

   }

  自动装配原理分析  从@SpringbootApplication入手分析

Springboot自动装配原理_自动装配原理

springboot自动装配流程图 

Springboot自动装配原理_自动装配原理

让我们仔细分析 

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports

public class AutoConfigurationImportSelector                                                                                                                                          implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,                                                          BeanFactoryAware, EnvironmentAware, Ordered {

@Override

public String[] selectImports(AnnotationMetadata annotationMetadata) {

          if (!isEnabled(annotationMetadata)) {

                  return NO_IMPORTS;

}

          AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader                                                                     .loadMetadata(this.beanClassLoader);

          AnnotationAttributes attributes = getAttributes(annotationMetadata);

          //去mata-info/spring.factories文件中 查询 EnableAutoConfiguration对于值

          List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

          //去除重复的配置类,若我们自己写的starter 可能存主重复的

          configurations = removeDuplicates(configurations);                                                                                                                 Set<String> exclusions = getExclusions(annotationMetadata, attributes);                                                                                checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions);

         //根据maven 导入的启动器过滤出 需要导入的配置类

         configurations = filter(configurations, autoConfigurationMetadata);                                                                                           fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations);

     }

}

//去spring.factories 中去查询EnableAutoConfirution类

 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {                                                   MultiValueMap<String, String> result = cache.get(classLoader);

                 if (result != null) {

                         return result;

                 }

                try {            

                     Enumeration<URL> urls = (classLoader != null ?                                                                                                                                        classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :                                                                                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));                                                        result = new LinkedMultiValueMap<>();

                       while (urls.hasMoreElements()) {

                               URL url = urls.nextElement();

                               UrlResource resource = new UrlResource(url);                                                                                                                         Properties properties = PropertiesLoaderUtils.loadProperties(resource);

                               for (Map.Entry<?, ?> entry : properties.entrySet()) {

                                        List<String> factoryClassNames = Arrays.asList(                                                                                                                                     StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));                                                                 result.addAll((String) entry.getKey(), factoryClassNames);

                               }

                      }

                     cache.put(classLoader, result);

                     return result; }

catch (IOException ex) {

                    throw new IllegalArgumentException(“Unable to load factories from location [” +                                                                                     FACTORIES_RESOURCE_LOCATION + “]”, ex); } }

Springboot自动装配原理_自动装配原理 

然后我们分析RedisAutoConfiguration类

     导入了三个组件  RedisTemplate   StringRedisTemplate

     JedisConnectionConfiguration 

Springboot自动装配原理_自动装配原理

Springboot自动装配原理_自动装配原理

 Springboot自动装配原理_自动装配原理

Springboot自动装配原理_自动装配原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171425.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 【面试真经】2020年7月 Linux运维面试题(含答案版)

    【面试真经】2020年7月 Linux运维面试题(含答案版)一.在当前文件目录下,有文件file1查询file1里面空行的所在行号查询file2以abc结尾的行打印出file1文件第一行到第3行二.如何将本地80端口的请求转发到8080端口,当前的主机IP为192.168.2.1三.crontab如何设置在11月份的每天早上6点到12点中,每隔2个小时执行/usr/bin/httpd.sh怎么实现四.编写个shell脚本将/usr/local/test目录下大于100K的文件转移到/tmp目录下五.简述raid0ra

  • 两种求集合全部子集的方法

    两种求集合全部子集的方法

  • 一些非常有价值的资料网站有哪些_比较有价值的网站

    一些非常有价值的资料网站有哪些_比较有价值的网站最近在搜集资料的时候,发现了很多好的资料网站,不忍独享,陆续整理出来,贴这里。我先有一个贴一个,等到攒到足够多的时候,我再重新进行整理:电影类:IMDb:http://www.imdb.com/(美国著名互联网电影资料库(InternetMovieDatabase,简称IMDb)是一个关于电影演员、电影、电视节目、电视明星、电子游戏和电影制作的在线数据库。亚马逊公司旗下网站)烂番茄…

  • 单片机—HLK-W801并口驱动ST7789

    介绍了w801上并口驱动sT7789的开发

  • python到底是什么类型的语言

    python到底是什么类型的语言写程序方便对做机器学习的人来说非常重要,因为经常需要对模型进行各种各样的修改,这在编译语言里很可能是牵一发而动全身的事情,而Python语言则可以用更少的时间来实现,因此Python语言几乎成为了人工

  • 巧用ViewPager 打造不一样的广告轮播切换效果

    巧用ViewPager 打造不一样的广告轮播切换效果转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/51339751;本文出自:【张鸿洋的博客】一、概述如果大家关注了我的微信公众号的话,一定知道我在5月6号的时候推送了一篇文章,文章名为Android超高仿QQ附近的人搜索展示(一),通过该文可以利用ViewPager实现单页显示多个Item且能够添加一些炫酷的动画效

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号