Springboot在容器启动时创建并初始化Bean

    技术2023-09-30  71

    场景:

    在容器启动时,我们需要去创建并初始化一个Bean,比如打开一个socket连接获取到Client(我之前写过的一个关于监听QQ消息的插件的使用,就可以使用这种方式初始化获取socket)。

    解决方法:

    首先,我们将假设的ClientService创建出来(因为只是为了快速达到效果,所以没有使用真正的Bean,但还是做了一些简单的修饰操作的)

    /** * @author: jaiaxn * @date: 2020年07月03日 * @description: 模拟一个必须在容器创建时就创建的bean **/ @Slf4j public class DemoClientService { private static DemoClientService clientService; /** * 初始化方法 */ public static DemoClientService initClient(String url, String username, String password) { return initClient(url, username, password, false); } /** * 初始化方法 */ public static DemoClientService initClient(String url, String username, String password, boolean skipVerify) { log.info("------------>DemoClientService init<------------"); if (null != url && null != username && null != password) { if (null == clientService) { clientService = new DemoClientService(); } log.info("------------>DemoClientService init success<------------"); return clientService; } log.info("------------>DemoClientService init failed<------------"); return null; } /** * 销毁方法 */ public static void closeClient(){ log.info("------------>DemoClientService closed!<------------"); } /** * 测试方法 * * @param something 入参 * @return result */ public String doSomething(String something){ log.info("------------>DemoClientService do {}<------------", something); return "SUCCESS"; } }

    可以看到其中有一些url等配置,我们将其放在配置文件中,使用ConfigurationProperties的方式去获取

    demo: client: url: http://127.0.0.1:8080/ username: demo password: demo skipVerify: true import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @author: jaiaxn * @date: 2020年07月03日 * @description: DemoClient相关配置 **/ @Data @Component @ConfigurationProperties(prefix = "demo.client") public class DemoClientProperties { private String url; private String username; private String password; private boolean skipVerify = false; }

    接下来我们去写一个操作客户端的接口,包含创建、销毁、获取三个方法

    /** * @author: jaiaxn * @date: 2020年07月03日 * @description: 操作客户端接口 **/ public interface IDemoClient { /** * 连接客户端 */ void connect(); /** * 关闭客户端 */ void disconnect(); /** * 获取真实客户端 * * @return 真实客户端 */ Object getNativeClient(); } /** * @author: jaiaxn * @date: 2020年07月03日 * @description: 操作客户端接口实现类 **/ public class DemoClient implements IDemoClient { private DemoClientService demoClientService; private final DemoClientProperties demoClientProperties; public DemoClient(DemoClientProperties demoClientProperties) { super(); this.demoClientProperties = demoClientProperties; } @Override public void connect() { demoClientService = DemoClientService.initClient(demoClientProperties.getUrl(), demoClientProperties.getUsername(), demoClientProperties.getPassword()); } @Override public void disconnect() { DemoClientService.closeClient(); } @Override public Object getNativeClient() { return demoClientService; } }

    下面就可以写我们的创建Bean以及初始化使用配置类了

    import com.jaiaxn.adaptation.config.client.DemoClient; import com.jaiaxn.adaptation.config.client.DemoClientProperties; import com.jaiaxn.adaptation.config.client.DemoClientService; import com.jaiaxn.adaptation.service.AdaptationService; import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * @author: jaiaxn * @date: 2020年07月03日 * @description: 初始化一个必须在容器创建时就创建的bean,在本示例中,我将改该Bean的创建初始化放在了Mybatis初始化完成之后,这个可以根据自身需要变更 **/ @Configuration @AutoConfigureAfter({MybatisAutoConfiguration.class}) @ComponentScan(basePackages = {"com.jaiaxn.adaptation"}) @EnableConfigurationProperties({DemoClientProperties.class}) @EnableTransactionManagement public class DemoServiceAutoConfiguration implements InitializingBean { private final ApplicationContext context; private final DemoClientProperties demoClientProperties; public DemoServiceAutoConfiguration(ApplicationContext context, DemoClientProperties demoClientProperties) { this.context = context; this.demoClientProperties = demoClientProperties; } /** * 创建DemoClient * * @return DemoClient */ @Bean(name = "demoClient", destroyMethod = "disconnect") public DemoClient sealClient() { DemoClient client = new DemoClient(demoClientProperties); client.connect(); return client; } /** * 初始化并将DemoClient注入要使用的Bean中去 */ @Override public void afterPropertiesSet() { DemoClient demoClient = context.getBean(DemoClient.class); DemoClientService demoClientService = (DemoClientService) demoClient.getNativeClient(); if (null != demoClientService) { AdaptationService adaptationService = context.getBean(AdaptationService.class); adaptationService.initServiceClient(demoClientService); } } }

    对了,还有一个类,是使用到DemoClientService的类,也给到大家

    import com.jaiaxn.adaptation.config.client.DemoClientService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * @author: jaiaxn * @date: 2019年07月08日 * @description: 使用到DemoClientService的类 **/ @Slf4j @Service public class AdaptationService { private DemoClientService demoClientService; public void initServiceClient(DemoClientService demoClientService) { this.demoClientService = demoClientService; } /** * do something */ public String doSomething(String something){ log.info("AdaptationService.doSomething req={}", something); return demoClientService.doSomething(something); } }

    最终效果:

    首先是项目启动时,可以看到我创建、初始化的日志

    本项目配置了Swagger,测试效果如下

    在停止项目时,可以看到自动调用销毁的方法

    结语:

    总的来说,就是用到了Springboot的AutoConfigureAfter以及InitializingBean的afterPropertiesSet方法。

    这里只是给大家提供了一种方法,欢迎各位大佬点评!谢谢!

     

    Processed: 0.010, SQL: 9