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启动流程

    镜花水月
  • 相关阅读:
    SharePoint 2010 User Profile Sync Service自动停止
    如何区别多个svchost.exe?
    Log Parser分析IIS log的一个简单例子
    Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
    Windows中右键点击文件夹, 结果找不到共享选项卡, 怎么办?
    介绍SOS中的SaveModule命令
    SharePoint中Draft版本的文档不会收到document added的Alert Email
    和我一起学Windows Workflow Foundation(1)创建和调试一个WF实例
    门户网站
    C#基础—— check、lock、using语句归纳
  • 原文地址:https://www.cnblogs.com/fengbingshui/p/13813875.html
Copyright © 2011-2022 走看看