Springboot 之 集成第三方技术和自动装配原理

Springboot 之 集成第三方技术和自动装配原理
一、整合 redis

  • 采用传统ssm整合redis的方式 。这里用springboot 代替ssm

  • 添加redis 依赖

<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>
  • 添加spring 配置文件applicationContext.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- redis连接池 -->
    <bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="600"></property>
        <property name="maxIdle" value="300"></property>
        <property name="maxWaitMillis" value="10000"></property>
        <property name="testOnBorrow" value="true"></property>
    </bean>
    <!-- redis连接工厂 -->
    <bean id="connectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="127.0.0.1"></property>
        <property name="port" value="6379"></property>
        <property name="password" value="test123"></property>
        <property name="poolConfig" ref="jedisConfig"></property>
    </bean>
    <!-- redis操作模板,这里采用尽量面向对象的模板 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <!--     如果不配置Serializer,那么存储的时候只能使用String,如果用对象类型存储,那么会提示错误 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.StringRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <!--开启事务-->
        <!--<property name="enableTransactionSupport" value="true"/>-->
    </bean>

</beans>
  • 使用@ImportResource(locations = “classpath:applicationContext.xml”) 注解加载配置问件操作redis
package com.huonilaifu.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author: lirb
 * @date: 2019/4/24
 * @description:
 */
@SpringBootApplication
@ImportResource(locations = "classpath:applicationContext.xml")
@RestController
public class MyOpenAutoconfigPrincipleApplication {
    @Autowired
    private RedisTemplate redisTemplate;

    public static void main(String[] args) {
        SpringApplication.run(MyOpenAutoconfigPrincipleApplication.class, args);
    }

    @RequestMapping("/testRedis")
    public String testRedis() {
        redisTemplate.opsForValue().set("lirb123","孙悟空");
        System.out.println("存入值");
        String lirb123 = (String) redisTemplate.opsForValue().get("lirb123");
        System.out.println("获取值为"+lirb123);
        return "OK";

    }
}

  • 采用springboot方式整合redis

  • 添加springboot redis 起步依赖

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
  • 修改配置文件
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=test123
  • 直接使用
    在这里插入图片描述

通过传统的方式进行整合redis 会进行大量的xml配置,非常繁琐。而使用springboot自动装配 ,只需添加redis起步依赖,配置 redis参数即可使用。

二、 自动装配的重要注解和原理。

  • @import :用来导入ImportSelector 组件 或 导入 ImportBeanDefinitionRegistrar 组件

  • 导入ImportSelector 组件:

    创建一个service 实现类 ,没有@Service注解 ,通过 ImportSelector 导入。


public class MyServiceImpl implements MyService {

    @Override
    public void testService() {
        System.out.println("我是通过ImportSelector导入进来的service·····");
    }
}

自定义 一个ImportSelector 导入 service

public class MySelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.huonilaifu.Service.impl.MyServiceImpl"};
    }
}

使用@Import 注解 导入自定义的ImportSelector。

@Configuration
@Import(value = {MySelector.class})
public class MyConfig extends WebMvcConfigurerAdapter {

启动 访问
在这里插入图片描述

  • 导入 ImportBeanDefinitionRegistrar 组件

    创建一个 Dao 类,通过 ImportBeanDefinitionRegistrar导入。

public class MyDao {

    public  void testDao() {
        System.out.println("我是通过ImportBeanDefinitionRegistrar导入进来的Dao······");
    }
}

创建一个自定义ImportBeanDefinitionRegistrar ,添加 MyDao

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(MyDao.class);
        beanDefinitionRegistry.registerBeanDefinition("myDao",rootBeanDefinition);
    }
}

使用@Import注解 注册 ImportBeanDefinitionRegistrar 组件

@Configuration
@Import(value = {MySelector.class ,MyImportBeanDefinitionRegistrar.class})
public class MyConfig extends WebMvcConfigurerAdapter {

在MyserviceImpl 中注入MyDao 依赖,并在之前方法中调用dao方法,启动再次访问
在这里插入图片描述
说明两个组件都注册成功。

  • @Conditional , spring 底层条件装配的原理。
    比如:我有两个组件 A、B,A 依赖 B ,只有容器中有B组件,A组件才会被加载。

  • 创建 A 组件 、B组件

public class MyAComponent {
    
}

class MyBComponent {
}

  • 创建自定义Conditional ,条件是只有有B组件是才返回true
public class MyConditional implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        if (conditionContext.getBeanFactory().containsBean("myBComponent")) {
            return true;
        }
        return false;
    }
}

注册 A 、B 组件 ,并在A组件上添加@Conditional注解

@Bean
    public MyBComponent myBComponent(){
        System.out.println("B 组件 自动装配到容器中···");
        return new MyBComponent();
    }

    @Bean
    @Conditional( value = {MyConditional.class})
    public MyAComponent myAComponent(){
        System.out.println("A 组件 自动装配到容器中···");
        return new MyAComponent();
    }

在这里插入图片描述
启动,这种情况是 A、B组件都注册了,如果 不注册B 组件去掉B上的@Bean ,那么A也不会被注册

  • 自动装配原理分析, 从@SpringbootApplication入手分析
    在这里插入图片描述
    我们可以看到装载了 AutoConfigurationImportSelector类。
    debug 进入类
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            //去mata-info/spring.factories文件中 查询 EnableAutoConfiguration对于值
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            //去除重复的配置类,若我们自己写的starter 可能存主重复的
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            //根据maven 导入的启动器过滤出 需要导入的配置类
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

最后就是要装载的组件

mata-info/spring.factories 文件中查询的EnableAutoConfiguration ,一共118个
在这里插入图片描述
根据maven 导入的 启动器,最后过滤出需要导入的配置类
在这里插入图片描述

自动装配流程图

在这里插入图片描述
三、springboot 整合 持久层

  • 整合 jdbc
    添加maven依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

 配置文件 配置 jdbc 连接属性
spring.datasource.username=root
spring.datasource.data-password=root
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sso
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class HuoniSpringbootApplicationTests {


	@Autowired
	private DataSource dataSource;

	@Test
	public void contextLoads() {
	}

	@Test
	public void testDbType() {
		System.out.println("自动装配数据源的类型:"+dataSource.getClass());
	}
}

在这里插入图片描述

发布了14 篇原创文章 · 获赞 3 · 访问量 1965
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览