zoukankan      html  css  js  c++  java
  • springboot-01

    回调模式的概念

      回调模式是指:如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)。

    匿名类

    接口/父类类型 引用变量名 = new 接口/父类类型(){方法的重写};

    1、

    /*
    basicConsume(String queue, boolean autoAck, Consumer callback)
            参数:
                1. queue:队列名称
                2. autoAck:是否自动确认
                3. callback:回调对象
    
    */
            // 接收消息
            Consumer consumer = new DefaultConsumer(channel){
    
     /*               回调方法,当收到消息后,会自动执行该方法
    
                    1. consumerTag:标识
                    2. envelope:获取一些信息,交换机,路由key...
                    3. properties:配置信息
                    4. body:数据
    */
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("consumerTag:"+consumerTag);
    	 }
    };
    
    channel.basicConsume("hello_world",true,consumer);
    
    

    2、

     /**
         * 确认模式:
         * 步骤:
         * 1. 确认模式开启:ConnectionFactory中开启publisher-confirms="true"
         * 2. 在rabbitTemplate定义ConfirmCallBack回调函数
         */
        @Test
        public void testConfirm() {
    
            //2. 定义回调
            rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
                /**
                 *
                 * @param correlationData 相关配置信息
                 * @param ack   exchange交换机 是否成功收到了消息。true 成功,false代表失败
                 * @param cause 失败原因
                 */
                @Override
                public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                    System.out.println("confirm方法被执行了....");
    
                    if (ack) {
                        //接收成功
                        System.out.println("接收成功消息" + cause);
                    } else {
                        //接收失败
                        System.out.println("接收失败消息" + cause);
                        //做一些处理,让消息再次发送。
                    }
                }
            });
    
    public class RabbitTemplate{
            @FunctionalInterface
        public interface ConfirmCallback {
    		...
        }
    }
    

    自动配置

    ​ ---基于spring的java配置类的方式完成和第三方框架的整合

    springboot --> 提供一种快速使用spring的方式

    spring的配置 java配置类

    1、基于xml的配置

    2、基于Java的配置! --》提供一些配置类即可

    @Configuration 表明是一个注解类

    1、@Configuration

    @Configuration标注在类上相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文)

    @Configuration
    public class TestConfiguration {
        public TestConfiguration() {
            System.out.println("TestConfiguration容器启动初始化。。。");
        }
    }
    

    ||

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
           ...
    http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">
    
    
    </beans>
    
    2、@Configuration+@Bean

    @Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期

    @Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的<bean>,作用为:注册bean对象

    3、@Configuration+@Component+@ComponentScan

    @Configuration启动容器+@Component注册Bean +@ComponentScan(basePackages = "com.dxz.demo.configuration")扫描包中注解所标 注的类,如@Component、@Service、@Controller、@Repository。

    小结

    @Configuation等价于

    @Bean等价于

    @ComponentScan等价于<context:component-scan base-package=”com.zhu.demo”/>

    注解

    元注解:

    • @Target /目标

      用于声明注解的作用范围,例如作用范围为类、接口、方法等。

    • @Retention /保留

      声明了注解的生命周期,即注解在什么范围内有效。

    • @Documented /文档

      是一个标记注解,有该注解的注解会在生成 java 文档中保留。

    • @Inherited /继承

      表示修饰的自定义注解可以被子类继承

    https://blog.51cto.com/13586365/2065324

    https://www.fangzhipeng.com/java/2017/09/16/java-annotation.html

    spEL

    即Spring表达式语言

    可以在运行时查询和操作数据

    https://www.jianshu.com/p/e0b50053b5d3

    测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfig.class)
    
    //@RunWith(SpringRunner.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    //@SpringBootTest(classes = Demo01Application.class)
    @SpringBootTest
    //如果在引导类包的子包里(在test包下,包名一样),就不需要引导类.class了
    
    1、@RunWith

    @RunWith 就是一个运行器

    @RunWith(SpringJUnit4ClassRunner.class)

    ​ 让测试运行于Spring测试环 境,以便在测试开始的时候自动创建Spring的应用上下文

    2、@ContextConfiguration和@SpringBootTest

    https://www.cnblogs.com/bihanghang/p/10023759.html

    Spring的条件装配

        public @interface Conditional {
            Class<? extends Condition>[] value();
            /*
                    该注解可以接收一个Condition 的数组
                    Class类型的数组,可以存储Condition或者实现类
             */
            
            /*   ArrayList<? extends Number>
                //带通配符的泛型集合不能使用add方法
            */
        }
    
    • 自定义注解

      • 需要传入一个Class数组,并且需要继承Condition接口

      • 格式

        • public @interface 注解名称{
          	public 属性类型 属性名() default 默认值;
          }
          
    • 泛型

      • 类型通配符:<?>

      • 类型通配符上限:<? extends Number>

        • 类型是Number或者其子类型

        • ?都继承自Number,都在他下面

      • 类型通配符下限:<? super Number>

        • 类型是Number或者其父类型

        • ? 都比Number更大,都在他上面

    • Class类

    @Conditional注解可以添加在@Configuration、@Component、@Service等修饰的类上用于控制对应的Bean是否需要创建,或者添加在@Bean修饰的方法上用于控制方法对应的Bean是否需要创建。

    @Conditional添加在@Configuration修饰的类上,用于控制该类和该类里面所有添加的@Bean方法对应的Bean是否需要创建。

    Condition接口

        /**
         * context  上下文对象。用于获取环境,IOC容器,ClassLoader对象
         * metadata 注解元对象。 可以用于获取注解定义的属性值
         *          应用:导入通过注解值value指定坐标后创建Bean
         *          metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
         *              //Class.getNume()获取全类名
         *              //ConditionOnClass 实现了Condition接口的注解
         */
        public interface Condition {
            boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
        }
    

    切换内置服务器

    ---默认使用Tomcat服务器

    步骤

    1. 排除掉tomcat
    2. 引入别的依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    @Enable* 注解

    作用:用于动态启用某些功能的 =》加载@Configure配置类

    底层是使用@Import注解导入一些配置类,实现Bean的动态加载

    问题:SpringBoot工程是否可以直接获取jar包中定义的Bean? 不能

    原因:@ComponentScan 扫描范围 :当前引导类所在的包及其子包

    解决:

    1. 使用@ComponentScan 扫描

      1. @SpringBootApplication
        @ComponentScan("com.config")
        
    2. 使用@Import加载类,这些bean都会被spring创建,并放入到ioc容器

      1. public @interface Import {
        	Class<?>[] value(); //可以存任意的.class
            //ArrayList<?> 可以存任意
        }
        
      2. @SpringBootApplication
        @Import(UserConfig.class)
        
    3. @Import进行封装 -》 @Enable*

      1. @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface Import {
        	Class<?>[] value();
        }
        
      2. @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented                 //把Import注解上面的东西加进来,不可少
        @Import(UserConfig.class)
        public @interface EnableUser {
        
        }
        

    @Import详解

    1. 导入Bean

    2. 导入配置类

    3. 导入ImportSelector实现类,一般用于加载配置文件中的类

      1. public interface ImportSelector {
        	/**
        	 * Select and return the names of which class(es) should be imported based on
        	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
        	 * @return the class names, or an empty array if none
        	 */
        	String[] selectImports(AnnotationMetadata importingClassMetadata);
        }
        
    4. 导入ImportBeanDefinitionRegistrar实现类

      1. public interface ImportBeanDefinitionRegistrar {
        
        	/**
        	 * Register bean definitions as necessary based on the given annotation metadata of
        	 * the importing {@code @Configuration} class.
        	 * <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
        	 * registered here, due to lifecycle constraints related to {@code @Configuration}
        	 * class processing.
        	 * @param importingClassMetadata annotation metadata of the importing class
        	 * @param registry current bean definition registry
        	 */
        	void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
        }
        
      2. 使用

        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
                registry.registerBeanDefinition("user", beanDefinition);
            }
        

    @EnableAutoConfiguration

    1. @Import(AutoConfigurationImportSelector.class)
      public @interface EnableAutoConfiguration {
      }
      
    2. public class AutoConfigurationImportSelector implements DeferredImportSelector... 
      {
          	@Override
      	public String[] selectImports(AnnotationMetadata annotationMetadata) {
      		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
      				annotationMetadata);  //加载
      		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());//返回字符串数组
      	}
      }
      
    3. 	protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
         			AnnotationMetadata annotationMetadata) {
         		if (!isEnabled(annotationMetadata)) {
         			return EMPTY_ENTRY;
         		}
         		AnnotationAttributes attributes = getAttributes(annotationMetadata);
         		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
         		configurations = removeDuplicates(configurations);
         		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
         		checkExcludedClasses(configurations, exclusions);
         		configurations.removeAll(exclusions);
         		configurations = filter(configurations, autoConfigurationMetadata);
         		fireAutoConfigurationImportEvents(configurations, exclusions);
         		return new AutoConfigurationEntry(configurations, exclusions);
         	}
      
    4. 	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
         		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
         				getBeanClassLoader());
         		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
         				+ "are using a custom packaging, make sure that file is correct.");
         		return configurations;
         	}
      
    5. 例如

      1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=
        org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
        
      2. @Configuration
        @ConditionalOnClass({RedisOperations.class}) //条件
        @EnableConfigurationProperties({RedisProperties.class})
        @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
        public class RedisAutoConfiguration {
            public RedisAutoConfiguration() {
            }
            @Bean
            @ConditionalOnMissingBean(
                name = {"redisTemplate"}
            )
            public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
                return template;
            }
        
        

    自定义一个starter

    自己整合 分析mybatis

    1. 依赖

      1. <dependency>
        	<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-starter</artifactId>
        </dependency>
        
    2. 依赖传递

      1.    <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-autoconfigure</artifactId>
              <version>2.1.17.RELEASE</version>
              <scope>compile</scope>
            </dependency>
        

    自定义redis-starter步骤

    1. 自定义配置类工程redis-spring-boot-autoconfigure

      1. 导入相关依赖,引入jedis依赖

      2. 编写属性配置类,用于加载redis相关配置

        1. @ConfigurationProperties(prefix = "redis")
          public class RedisProperties {
              private String host = "localhost";
              private int port = 6379;
              //	get/set
          }
          
      3. 编写@Configuration配置类并实现条件装配

        1. @Configuration
          @EnableConfigurationProperties(RedisProperties.class)
          public class RedisAutoConfiguration {
              /**
               * 提供Jedis的bean
               */
              @Bean
              @ConditionalOnMissingBean(name = "jedis")
              public Jedis jedis(RedisProperties redisProperties) {  
                  return new Jedis(redisProperties.getHost(), redisProperties.getPort());
              }
          }
          
      4. 在META-INF/spring.factories中配置

        1. 在项目的resource目录下创建META-INF文件夹并创建spring.factories,内容如下
          
          org.springframework.boot.autoconfigure.EnableAutoConfiguration=
            com.itheima.redis.config.RedisAutoConfiguration
          
    2. 自定义起步依赖工程redis-spring-boot-starter

      1. 导入前面的依赖

    SpringBoot监听机制

    其实是对java提供的事件监听机制的封装

    ​ java监听机制定义了一下几个角色:

    1. 事件:Event,继承java.util.EventObject类的对象
    2. 事件源:Source,任意对象Object
    3. 监听器:Listener,实现java.util.EventListener接口的对象

    SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听接口,在项目启动时,完成一些操作

    1. ApplicationContextInitializer

      1. 需要配置

    2. SpringApplicationRunListener

    3. Runner

      1. 当项目启动时,自动装配

      2. CommandLineRunner

      3. ApplicationRunner

    SpringBoot启动流程

    镜花水月
  • 相关阅读:
    参数迭代的初始值
    印刷体、手写体公式图片OCR识别转latex
    混合型变量聚类的观点
    算法优化大概的方法
    梯度下降法
    支持向量机-可分的类
    LaTex希腊字母
    红黑树删除操作
    红黑树插入操作
    红黑树
  • 原文地址:https://www.cnblogs.com/fengbingshui/p/13813875.html
Copyright © 2011-2022 走看看