美文网首页
201009复盘:@Order-TimeUnit-decod

201009复盘:@Order-TimeUnit-decod

作者: 弹钢琴的崽崽 | 来源:发表于2020-10-11 14:00 被阅读0次

一. Spring @Order注解的使用

注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响

1. @Order的注解源码解读

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
    /**
     * 默认是最低优先级,值越小优先级越高
     */
    int value() default Ordered.LOWEST_PRECEDENCE;
}
  • 注解可以作用在类(接口、枚举)、方法、字段声明(包括枚举常量);
  • 注解有一个int类型的参数,可以不传,默认是最低优先级;
  • 通过常量类的值我们可以推测参数值越小优先级越高;

2. Ordered接口类

package org.springframework.core;

public interface Ordered {
    int HIGHEST_PRECEDENCE = -2147483648;
    int LOWEST_PRECEDENCE = 2147483647;

    int getOrder();
}

3. 创建BlackPersion、YellowPersion类,这两个类都实现CommandLineRunner

实现CommandLineRunner接口的类会在Spring IOC容器加载完毕后执行,适合预加载类及其它资源;也可以使用ApplicationRunner,使用方法及效果是一样的

a. pom依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
b. 主启动类
package com.rgh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApplicationMain {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationMain.class, args);
    }
}
c. 两个实体类
@Component
@Order(1)
public class BlackPersion implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("----BlackPersion----");
    }
}

@Component
@Order(0)
public class YellowPersion implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("----YellowPersion----");
    }
}

4. 启动应用程序打印出结果

----YellowPersion----
----BlackPersion----

我们可以通过调整@Order的值来调整类执行顺序的优先级,即执行的先后;当然也可以将@Order注解更换为Ordered接口,效果是一样的

5. 到这里可能会疑惑IOC容器是如何根据优先级值来先后执行程序的,那接下来看容器是如何加载component的

  • 看如下的启动main方法
@SpringBootApplication
public class CommonBootStrap {
    public static void main(String[] args) {
        SpringApplication.run(CommonBootStrap.class, args);
    }
}

这个不用过多的解释,进入run方法…

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();

    Collection exceptionReporters;
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        Banner printedBanner = this.printBanner(environment);
        context = this.createApplicationContext();
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        this.refreshContext(context);
        this.afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        listeners.started(context);
        //这里是重点,调用具体的执行方法
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}
private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList();
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    //重点来了,按照定义的优先级顺序排序
    AnnotationAwareOrderComparator.sort(runners);
    Iterator var4 = (new LinkedHashSet(runners)).iterator();
    //循环调用具体方法
    while(var4.hasNext()) {
        Object runner = var4.next();
        if (runner instanceof ApplicationRunner) {
            this.callRunner((ApplicationRunner)runner, args);
        }

        if (runner instanceof CommandLineRunner) {
            this.callRunner((CommandLineRunner)runner, args);
        }
    }

}

private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    try {
        //执行方法
        runner.run(args);
    } catch (Exception var4) {
        throw new IllegalStateException("Failed to execute ApplicationRunner", var4);
    }
}

private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
    try {
        //执行方法
        runner.run(args.getSourceArgs());
    } catch (Exception var4) {
        throw new IllegalStateException("Failed to execute CommandLineRunner", var4);
    }
}

到这里优先级类的示例及其执行原理都分析完毕;不过还是要强调下@Order、Ordered不影响类的加载顺序而是影响Bean加载如IOC容器之后执行的顺序(优先级);

二. TimeUnit 的使用

TimeUnit是java.util.concurrent包下面的一个类,表示给定单元粒度的时间段

主要作用

  • 时间颗粒度转换
  • 延时

常用的颗粒度

TimeUnit.DAYS          //天
TimeUnit.HOURS         //小时
TimeUnit.MINUTES       //分钟
TimeUnit.SECONDS       //秒
TimeUnit.MILLISECONDS  //毫秒

1. 时间颗粒度转换

public long toMillis(long d)    //转化成毫秒
public long toSeconds(long d)  //转化成秒
public long toMinutes(long d)  //转化成分钟
public long toHours(long d)    //转化成小时
public long toDays(long d)     //转化天

例子

public class Test {
    public static void main(String[] args) {
        //1天有24个小时    1代表1天:将1天转化为小时
        System.out.println( TimeUnit.DAYS.toHours( 1 ) );
        //结果: 24
        //1小时有3600秒
        System.out.println( TimeUnit.HOURS.toSeconds( 1 ));=
        //结果3600
        //把3天转化成小时
        System.out.println( TimeUnit.HOURS.convert( 3 , TimeUnit.DAYS ) );
        //结果是:72
    }
}

2. 延时

  • 一般的写法
public class Test2 {
    public static void main(String[] args) {
        new Thread( new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep( 5 * 1000 );
                    System.out.println( "延时完成了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();  ;
    }
}
  • TimeUnit 写法

    public class Test2 {
        public static void main(String[] args) {
            new Thread( new Runnable() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep( 5 );
                        System.out.println( "延时5秒,完成了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();  ;
        }
    }
    

三. oracle中的decode的使用

含义解释:
decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值)

该函数的含义如下:
IF 条件=值1 THEN
    RETURN(翻译值1)
ELSIF 条件=值2 THEN
    RETURN(翻译值2)
    ......
ELSIF 条件=值n THEN
    RETURN(翻译值n)
ELSE
    RETURN(缺省值)
END IF

decode(字段或字段的运算,值1,值2,值3)

这个函数运行的结果是,当字段或字段的运算的值等于值1时,该函数返回值2,否则返回值3
当然值1,值2,值3也可以是表达式,这个函数使得某些sql语句简单了许多

使用方法:

1. 比较大小

select decode(sign(变量1-变量2),-1,变量1,变量2) from dual;

--取较小值
sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1
例如:
变量1=10,变量2=20
则sign(变量1-变量2)返回-1,*decode*解码结果为“变量1”,达到了取较小值的目的。

2. 此函数用在SQL语句中,功能介绍如下:

Decode函数与一系列嵌套的 IF-THEN-ELSE语句相似。base_exp与compare1,compare2等等依次进行比较。如果base_exp和 第i 个compare项匹配,就返回第i 个对应的value 。如果base_exp与任何的compare值都不匹配,则返回default。每个compare值顺次求值,如果发现一个匹配,则剩下的compare值(如果还有的话)就都不再求值。一个为NULL的base_exp被认为和NULL compare值等价。如果需要的话,每一个compare值都被转换成和第一个compare 值相同的数据类型,这个数据类型也是返回值的类型。

Decode函数在实际开发中非常的有用

a. 结合Lpad函数,如何使主键的值自动加1并在前面补0
select LPAD(decode(count(记录编号),0,1,max(to_number(记录编号)+1)),14,'0') 记录编号 from tetdmis
补充:LPAD函数的用法
lpad('tech', 7); 将返回' tech'
lpad('tech', 2); 将返回'te'
lpad('tech', 8, '0'); 将返回'0000tech'
lpad('tech on the net', 15, 'z'); 将返回'tech on the net'
lpad('tech on the net', 16, 'z'); 将返回'ztech on the net'

例:

select decode(dir,1,0,1) from a1_interval

dir 的值是1变为0,是0则变为1

3. 比如我要查询某班男生和女生的数量分别是多少?

通常我们这么写:

select count(*) from 表 where 性别 = 男;
select count(*) from 表 where 性别 = 女;

要想显示到一起还要union一下,太麻烦了

用decode呢,只需要一句话

select sum(decode(性别,男,1,0)),sum(decode(性别,女,1,0)) from 表

4. order by对字符列进行特定的排序

大家还可以在Order by中使用Decode。

例:表table_subject,有subject_name列。要求按照:语、数、外的顺序进行排序。这时,就可以非常轻松的使用Decode完成要求了。

select * from table_subject order by decode(subject_name, '语文', 1, '数学', 2, , '外语',3)

相关文章

  • 201009复盘:@Order-TimeUnit-decod

    一. Spring @Order注解的使用 注解@Order或者接口Ordered的作用是定义Spring IOC...

  • 心得201009

    有一位退休的老人回到老家,在小城买了一座房住了下来,想在那儿安静些写回忆录。开始的几个星期,一切都好。但是有一天,...

  • 2018-08-25 相对位置绝对位置

    http://developer.51cto.com/art/201009/225201.htm

  • AAR复盘工具

    大家好, 我是阿萨。 复盘相信大家都听过。日复盘,周复盘,月复盘,年度复盘,工作复盘,项目复盘。生活中时时处处都会...

  • 团队复盘盘什么?

    导读: 1、什么是复盘? 2、为什么要复盘? 3、复盘盘什么 4、如何做好复盘 01 什么是复盘 复盘,本是围棋术...

  • 人生怎么能没有复盘!?

    说到复盘,现在特别流行,日复盘、周复盘、月复盘、演讲复盘等等,为什么要复盘?有句话是这样说的:没有复盘的人生是不会...

  • 【转】SQL中随机数函数rand()简介

    转载于:http://database.51cto.com/art/201009/224397.htm 51 ...

  • 盘点复盘(一)

    一、复盘三种类型 自我复盘、团队复盘和复盘他人。 自我复盘:是个人获得成长的方便手段。 团队复盘:可以让复盘主导人...

  • 复盘可以解决很多事

    越读复盘会发现,越在复盘实践中发现,复盘可以盘万事万物。 可以事件复盘,可以人物复盘,可以情绪复盘,只要掌握复盘思...

  • 复盘的三种类型

    复盘有三种类型:自我复盘、团队复盘和复盘他人。 自我复盘可以随时进行,是个人获得成长的方便手段。团队复盘可以让复盘...

网友评论

      本文标题:201009复盘:@Order-TimeUnit-decod

      本文链接:https://www.haomeiwen.com/subject/gyrepktx.html