# SpringSpringBoot 开发实用技巧

Posted MarlonBrando1998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# SpringSpringBoot 开发实用技巧相关的知识,希望对你有一定的参考价值。

Spring、SpringBoot 开发实用技巧

友情链接

SpringBoot 知识专栏: https://blog.csdn.net/qq_37248504/category_10924414.html

Spring 知识专栏: https://blog.csdn.net/qq_37248504/category_10924424.html

后端开发知识专栏: https://blog.csdn.net/qq_37248504/category_9699519.html

获取 ApplicationContext

直接注入

  • 直接在使用的地方注入使用
@Autowired
private ApplicationContext applicationContextBean;

实现ApplicationContextAware接口

  • 实例代码SpringContextUtils,定义全局的获取上下文的工具类
@Component
public class SpringContextUtils implements ApplicationContextAware 
    
    private static final Logger logger = LoggerFactory.getLogger(SpringContextUtils.class);

    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext = null;


    private SpringContextUtils() 
    

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
        if (Objects.isNull(SpringContextUtils.applicationContext)) 
            logger.info(LogConst.LOG_SUCCESS_PREFIX + "ApplicationUtils初始化...");
            SpringContextUtils.applicationContext = applicationContext;
        
        logger.info(LogConst.LOG_SUCCESS_PREFIX + "ApplicationUtils初始化成功!");
    

    /**
     * 获得当前的ApplicationContext
     *
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() 
        return applicationContext;
    

    /**
     * 根据名称拿到 Bean
     *
     * @param name Bean 的名称
     * @return Object
     */
    @SuppressWarnings("all")
    public static Object getBean(String name) 
        return getApplicationContext().getBean(name);
    

    /**
     * 从ApplicationContext中获得Bean并且转型
     *
     * @param tClass 类
     * @param <T>    T
     * @return T
     */
    public static <T> T getBean(Class<T> tClass) 
        return getApplicationContext().getBean(tClass);
    

作为参数获取 ApplicationContext Bean

  • Spring在初始化AutoConfiguration时会自动传入ApplicationContext,这时我们就可以使用下面的方式来获取ApplicationContext
@Configuration
public class TestConfig 

    private static final Logger logger = LoggerFactory.getLogger(TestConfig.class);

    /**
     * 作为参数获取 Bean
     *
     * @param applicationContext applicationContext
     */
    public TestConfig(ApplicationContext applicationContext) 
        logger.info(String.valueOf(applicationContext));
    

启动时获取ApplicationContext

  • 在启动Spring Boot项目时,需要调用SpringApplication.run()方法,而run()方法的返回值就是ApplicationContext,我们可以把run()方法返回的ApplicationContext对象保存下来,方便随时使用:
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@MapperScan("com.li.springbootproject.mapper")
@EnableAspectJAutoProxy
public class SpringBootProjectApplication 

    private static final Logger logger = LoggerFactory.getLogger(SpringBootProjectApplication.class);

    public static void main(String[] args) 
        ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringBootProjectApplication.class, args);
        logger.info(LogConst.LOG_SUCCESS_PREFIX + "启动成功:" + applicationContext);
    

通过WebApplicationContextUtils获取

Spring提供了一个工具类用于获取ApplicationContext对象:

@Autowired
private ServletContext servletContext;

@Override
public String testSix() 
    WebApplicationContext context1 = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
    WebApplicationContext context2 = WebApplicationContextUtils.getWebApplicationContext(servletContext);
    return "测试成功!";

Bean的初始化

实现InitializingBean接口

  • InitializingBean接口在org.springframework.beans.factory包中,这种方法官方不建议使用,框架层使用该方式。
@Configuration
public class PeopleBean implements InitializingBean 

    private static final Logger logger =  LoggerFactory.getLogger(PeopleBean.class);

    private int id;

    private String name;

    @Bean
    public PeopleBean peopleBeanInit()
        PeopleBean peopleBeanInit = new PeopleBean();
        peopleBeanInit.setId(this.id);
        peopleBeanInit.setName(this.name);
        return peopleBeanInit;
    

	// 对象属性赋值
    @Override
    public void afterPropertiesSet() throws Exception 
        logger.info("=====> 我要对peoplebean 进行初始化!");
        this.id = 100;
        this.name = "李四";
    

@PostConstruct注解的使用

@Configuration
public class PeopleOneBeanInit 

    private int id;

    private String name;

    @Bean
    public PeopleOneBeanInit peopleOneBean()
        PeopleOneBeanInit peopleOneBean = new PeopleOneBeanInit();
        peopleOneBean.setId(this.id);
        peopleOneBean.setName(this.name);
        return peopleOneBean;
    

	// 使用这个注解可以在这进行对该类属性初始化操作。
    @PostConstruct
    public void init()
        this.id = 1001;
        this.name = "测试张三";
    

Spring xml配置方式

<bean id="helloWorld" class="com.li.entity.HelloWorld" scope="singleton" init-method="init" destroy-method="destroy">
</bean>
public class HelloWorld 
   public void init() 
      // 在这里可以对对象属性进行初始化
   

  • 注解方式
@Configuration
public class PeopleTwoConfig 

    /**
     * 相当与xml方式配置中的init-method
     * @return
     */
    @Bean(initMethod = "init")
    public PeopleTwoBeanInit peopleTwoBeanInit()
        return new PeopleTwoBeanInit();
    



public class PeopleTwoBeanInit 
    public void init()
        this.id = 1005;
        this.name = "李四测试1";
    

修改Bean的属性信息

实现 BeanPostProcessor 接口

实现BeanPostProcessor 接口,重写postProcessBeforeInitialization()postProcessAfterInitialization(),在重写的方法中,可以获得Bean的属性,对Bean进行相关的操作。

@Component
public class UserBeanPostProcessor implements BeanPostProcessor 

    private static final Logger logger = Logger.getLogger(String.valueOf(UserBeanPostProcessor.class));

	// 在这里可以拿到bean的相关信息,进行相关操作
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
        final String name = "myUser";
        if(name.equals(beanName))
            User user = (User) bean;
            user.setName("李四");
            user.setDate(new Date());
            logger.info("=====> postProcessBeforeInitialization():"+ JSONObject.toJSONString(user));
        
        return bean;
    

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        return bean;
    


获取BeanFactory

Spring中的Aware

Aware这个类主要是辅助Spring进行访问容器中的数据,在实现这个类重写的方法中,可以拿到相关组件的信息,从而可以进行相应的扩展。

常用的Aware实现类

  • BeanFactoryAware:获取BeanFactory容器
  • BeanNameAware:获取Bean的名称
  • ApplicationContextAware:获取ApplicationContext

得到 BeanFactory

实现BeanFactoryAware,在setXXX()中获得相关的Spring组件。

@Component
public class GetBeanFactory implements BeanFactoryAware 

    private static final Logger logger = LoggerFactory.getLogger(GetBeanFactory.class);

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException 
        this.beanFactory = beanFactory;
        MyBeans bean = beanFactory.getBean(MyBeans.class);
        logger.info("-----> 获得当前的BeanFactory "+ beanFactory);
    



服务启动后加载资源

  • springboot给我们提供了两种“开机启动”方式:ApplicationRunnerCommandLineRunner

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

Order 注解使用

  • Spring容器启动后可以加载一些资源或者做一些业务操作
  • 实现 CommandLineRunner
@Component
@Order(1)
public class OrderTestOne implements CommandLineRunner 

    private static final Logger logger = LoggerFactory.getLogger(OrderTestOne.class);

    /**
     * 执行
     *
     * @param args 参数
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception 
        logger.info("OrderTestOne...");
    

  • order的值越小,优先级越高
  • order如果不标注数字,默认最低优先级,因为其默认值是int最大值

实现 ApplicationRunner、Ordered 接口

@Component
public class OrderTestTwo implements ApplicationRunner, Ordered 

    private static final Logger logger = LoggerFactory.getLogger(OrderTestTwo.class);

    /**
     * 执行
     *
     * @param args 参数
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception 
        logger.info("OrderTestTwo...");
    

    /**
     * 定义执行的顺序
     *
     * @return int
     */
    @Override
    public int getOrder() 
        return 2;
    

Fluent Builder API

  • SpringApplicationBuilder允许您将多个方法调用链接在一起,并包含父方法和子方法,这些方法允许您创建层次结构,如下面的示例所示:
new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .bannerMode(Banner.Mode.OFF)
        .run(args);

应用程序退出

每个 SpringApplication 注册了一个 JVM 关闭钩子,以确保 ApplicationContext 在退出时可以优雅关闭。所有标准的 Spring 生命周期回调(比如 DisposableBean 接口,或者 @PreDestroy 注解)都可以使用。

此外,如果希望在调用 SpringApplication.exit() 时返回特定的退出码,则 bean 可以实现 org.springframework.boot.ExitCodeGenerator 接口。之后退出码将传递给 System.exit() 以将其作为状态码返回,如示例所示:

@SpringBootApplication
public class ExitCodeApplication 

    @Bean
    public ExitCodeGenerator exitCodeGenerator() 
        return () -> 100;
    

    public static void main(String[] args) 
        System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
    

继承 Starter Parent

  • 要将项目配置继承 spring-boot-starter-parent,只需要按以下方式设置 parent
<!-- 从 Spring Boot 继承默认配置 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
</parent>

注意

您只需要在此依赖上指定 Spring Boot 的版本号。如果您要导入其它 starter,则可以放心地省略版本号。

通过该设置,您还可以重写自己项目中的配置属性来覆盖个别依赖。例如,要升级到另一个 Spring Data 发行版本,您需要将以下内容添加到 pom.xml 文件中。

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

读取配置文件中的属性注册 Bean

  • 定义Bean
@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties 

    private String host;

    private int port;

    private int timeout;

    private String password;
    
    // 省略 getset

  • yml中定义属性值
spring:
	redis:
    	host: 127.0.0.1
    	port: 6379
    	password:

SpringBoot Event 事件同步、异步处理

  • Spring 中,初始化容器时会调用 org.springframework.context.ConfigurableApplicationContext 接口中的 reFresh() 方法进行 Be~an的加载,该方法会进行事件的监听注册。

  • 事件机制详细内容见地址:https://blog.csdn.net/qq_37248504/article/details/115269995

以上是关于# SpringSpringBoot 开发实用技巧的主要内容,如果未能解决你的问题,请参考以下文章

springspringboot定时任务

SpringSpringBoot 2.6.4配置跨域

SpringSpringBoot 2.6.4配置跨域

springspringboot静态资源导入探究

SpringSpringBoot集成邮箱发送

SpringSpringboot常用注解:@Qualifier(不定时更新)