如何在项目启动时就执行某些操作

版权声明:本文为博主原创文章,无需授权即可转载,甚至无需保留以上版权声明,转载时请务必注明作者。 https://blog.csdn.net/lmb55/article/details/90413830

参考资料:如何在项目启动时就执行某些操作

在实际的项目开发中经常会遇到一些需要在项目启动的时候进行初始化操作的需求,比如初始化线程池,配置某些对象的序列化和反序列化方式,加载黑名单白名单,加载权限应用,加载组织架构到缓存等等。这篇文章就来总结一下如何在项目初始化时进行一些资源操作。

方法一:@PostConstruct方法

//将黑名单从数据库中查询出来,并放到缓存中
@Service("phoneBlacklistCache")
public class PhoneBlacklistCache {
  public List<String> phoneBlacklist = new ArrayList<String>();
 
 @PostConstruct
  public void init(){     
    //需要进行的操作,如:查询数据库,写到缓存
    }
}

方法二:init-method方法

1、在xml文件里配置bean,bean的配置中配置init-method方法(该方法配置成你想要执行的操作方法)。

<bean id="PoneBlacklistCache" class="com.xxx.cache.PhoneBlacklistCache" scope="singleton"  init-method="init"></bean>

2、通过@Bean注解的方式

@Service("phoneBlacklistCache")
public class PhoneBlacklistCache {
  public List<String> phoneBlacklist = new ArrayList<String>();
  
@Bean(initMethod = “init”)
  public void init(){     
    //需要进行的操作,如:查询数据库,写到缓存
    }
}

方法三:InitializingBean方法

让相应的类实现InitializingBean接口,重写InitializingBean接口的afterPropertiesSet方法即可。

public class PhoneBlacklistCache implements InitializingBean{
      public List<String> phoneBlacklist = new ArrayList<String>();
      @Override
      public void afterPropertiesSet() throws Exception {     
       //需要进行的操作,比如查询数据库,写到缓存
     }
 }

方法四:quartz方法

将定时任务(如:SimpleTriggerBean等)配置成项目启动后立即执行,且重复执行次数配置成0次,不重复执行,即可达到项目启动时执行一些操作的目的。

方法五:在springboot启动类的main方法中执行

@SpringBootApplication
public class TestApplication {
	public static void main(String[] args) {
		System.out.println(" doSomething……");
		SpringApplication.run(CommandLineRunnerApplication.class, args);
		System.out.println(" doSomething……");
	}
}

方法六:实现CommandLineRunner/ApplicationRunner接口

CommandLineRunner 接口的 Component 会在所有 SpringBeans都初始化之后, SpringApplication.run()之前执行,非常适合在应用程序启动之初进行一些数据初始化的工作。

@SpringBootApplication
public class TestCommandLineRunnerApplication {
	public static void main(String[] args) {
		System.out.println("The service to start.");
		SpringApplication.run(CommandLineRunnerApplication.class, args);
		System.out.println("The service has started.");
	}
}

实现CommandLineRunner接口

@Component
public class Runner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("The Runner start to initialize ...");
}
}

控制台打印结果

...
The service to start.
 
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.0.RELEASE)
...
2018-04-21 22:21:34.706  INFO 27016 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-04-21 22:21:34.710  INFO 27016 --- [           main] com.xxx.TestCommandLineRunnerApplication     : Started TestCommandLineRunnerApplication in 3.796 seconds (JVM running for 5.128)
The Runner start to initialize ...

如果我们在启动容器的时候需要初始化很多资源,并且初始化资源相互之间有序,那如何保证不同的 CommandLineRunner的执行顺序呢?Spring Boot 也给出了解决方案。那就是使用 @Order 注解。

实现类一

@Component
@Order(1)
public class OrderRunner1 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("The OrderRunner1 start to initialize ...");
    }
}

实现类二

@Component
@Order(2)
public class OrderRunner2 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("The OrderRunner2 start to initialize ...");
    }
}

控制台执行结果如下

...
The service to start.
 
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.0.RELEASE)
...
2018-04-21 22:21:34.706  INFO 27016 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-04-21 22:21:34.710  INFO 27016 --- [           main] com.xxx.TestCommandLineRunnerApplication     : Started TestCommandLineRunnerApplication in 3.796 seconds (JVM running for 5.128)
The OrderRunner1 start to initialize ...
The OrderRunner2 start to initialize ...
The Runner start to initialize ...

通过控制台的输出我们发现,添加 @Order 注解的实现类最先执行,并且@Order()里面的值越小启动越早。

对比:

相同点:这两种方法提供的目的是为了满足,在项目启动的时候立刻执行某些方法。我们可以通过实现ApplicationRunner和CommandLineRunner,来实现,他们都是在SpringApplication 执行之后开始执行的。

不同点:CommandLineRunner接口可以用来接收字符串数组的命令行参数,ApplicationRunner 是使用ApplicationArguments 用来接收参数的 【根据业务场景灵活运用】

ApplicationRunner源码如下:

public interface ApplicationRunner {

    void run(ApplicationArguments var1) throws Exception;
}

CommandLineRunner源码如下

public interface CommandLineRunner {

   void run(String... var1) throws Exception;
}
展开阅读全文

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