# Spring、SpringBoot 开发实用技巧

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
资源介绍 本资源包为基于Spring Boot开发的精简博客系统的设计与实现,涵盖了从需求分析、系统设计到具体实现的完整过程,并附带了完整的毕业论文及毕设源代码。此博客系统旨在提供一个轻量级、易扩展的博客平台,适用于个人或小团队快速搭建自己的博客站点。 在设计上,系统采用了前后端分离的开发模式,前端使用现代化的前端框架进行构建,后端则依托Spring Boot的快速开发特性,结合Spring MVC、MyBatis等技术,实现了高效、稳定的数据处理与业务逻辑。同时,系统支持用户注册登录、文章发布编辑、评论互动等基本功能,满足了博客系统的基础需求。 在实现上,本系统注重代码的规范性与可维护性,采用了模块化、分层化的设计思路,使得代码结构清晰、易于扩展。同时,系统还引入了Redis缓存、分布式事务处理等高级特性,提升了系统的性能与稳定性。 此外,毕业论文详细记录了本博客系统的开发过程,从需求分析、系统设计到编码实现,都进行了深入的探讨与总结。通过阅读毕业论文,读者不仅可以了解本系统的开发思路与实现方法,还可以学习到Spring Boot等技术的使用技巧与最佳实践。 最后,毕设源代码已进行精心整理与注释,方便读者阅读与学习。同时,源代码具有良好的可扩展性与可定制性,读者可以根据自身需求进行二次开发,实现更多个性化的功能。 总之,本资源包为基于Spring Boot开发的精简博客系统的设计与实现提供了全面的指导与参考,无论是对于初学者还是有一定经验的开发者,都具有很高的学习价值与实用价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值