最近一直想整理一篇关于springboot优化和注释的文章,今天恰好在“大侠学Java”的公众号上看见了一篇相关的文章,整理一下以供自己和大家一起学习
那现在就让我们一起打开spring的优化妙招之门
一、springboot的优化小妙招
- 代码模块化
阿里巴巴开发手册说程序单个方法的极限行数最好不要超过80行,这个是提供大家参考的一个规范,这也许这是他们内部程序员写代码的一种习惯,但是像这种大厂遵循的规则,应该是通过大量的理论加实践得出来的一个有效的规约。所以在实际的开发中我们要善于拆分自己的接口,说不定哪一个功能在不久的将来就能用到了,拿来即用 - 抛异常而不是返回null
在写业务代码的时候,经常会根据不同的结果返回不同的信息,尽量减少返回,会显得代码比较乱。
反例 - 正例
- 减少不必要的db
尽可能的减少对数据库的查询
举例子
删除一个服务(已下架或未上架的才能删除),之前有看别人写的代码,会先根据id查询该记录,然后做一些判断。
反例
正例
- 不要返回null
反例
正例 - 不要使用大量的if-else
可以使用策略模式、枚举、optional来代替
二、springboot好用的注解们
- bean相关
. @Service
常用于修饰service层的组件,声明一个对象,会将类对象实例化并注入到bean容器里面。
@Service
public class UpdateService{
//具体方法
}
. @Component
泛指组件,当组件不好归类的时候,可以使用这个注解进行标注
@Component
public class DeptDo{
//业务逻辑
}
. @Repository
用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件
@Repository注解属于Spring里面最先引入的一批注解,它用于将数据访问层 (DAO层 ) 的类标识为Spring Bean,具体只需将该注解标注在 DAO类上即可,示例代码如下:
@Repository
public interface RoleRepository extends JpaRepository<Role,Long> {
//具体的方法
}
为什么现在使用的很少呢?
主要是因为当我们配置服务启动自动扫描dao层包时,Spring会自动帮我们创建一个实现类,然后注入到bean容器里面。当某些类无法被扫描到时,我们可以显式的在数据持久类上标注@Repository注解,Spring会自动帮我们声明对象。
. @Bean
相当于 xml 中配置 Bean,意思是产生一个 bean 对象,并交给spring管理,示例代码如下:
@Configuration
public class AppConfig {
//相当于 xml 中配置 Bean
@Bean
public Uploader initFileUploader() {
return new FileUploader();
}
}
. @Autowired
自动导入依赖的bean对象,默认时按照byType方式导入对象,而且导入的对象必须存在,当需要导入的对象并不存在时,我们可以通过配置required = false来关闭强制验证。
@Autowired
private DeptService deptService;
. @Resource
也是自动导入依赖的bean对象,由JDK提供,默认是按照byName方式导入依赖的对象;而@Autowired默认时按照byType方式导入对象,当然@Resource还可以配置成通过byType方式导入对象。
/**
* 通过名称导入(默认通过名称导入依赖对象)
*/
@Resource(name = "deptService")
private DeptService deptService;
/**
* 通过类型导入
*/
@Resource(type = RoleRepository.class)
private DeptService deptService;
. Qualifier
当有多个同一类型的bean时,使用@Autowired导入会报错,提示当前对象并不是唯一,Spring不知道导入哪个依赖,这个时候,我们可以使用@Qualifier进行更细粒度的控制,选择其中一个候选者,一般于@Autowired搭配使用,示例如下:
@Autowired
@Qualifier("deptService")
private DeptService deptService;
- 配置相关注解
. @Configuration
表示声明一个 Java 形式的配置类,Spring Boot 提倡基于 Java 的配置,相当于你之前在 xml 中配置 bean,比如声明一个配置类AppConfig,然后初始化一个Uploader对象。
@Configuration
public class AppConfig {
@Bean
public Uploader initOSSUploader() {
return new OSSUploader();
}
}
. @EnableAutoConfiguration
@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置类,全部都加载到当前SpringBoot里,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。
某些场景下,如果我们想要避开某些配置类的扫描(包括避开一些第三方jar包下面的配置,可以这样处理。
@Configuration
@EnableAutoConfiguration(exclude = { org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
public class AppConfig {
//具有业务方法
}
. @EnableTransactionManagement
表示开启事务支持,等同于 xml 配置方式的<tx:annotation-driven />
@SpringBootApplication
@EnableTransactionManagement`
public class PropertyApplication {
public static void main(String[] args) {
SpringApplication.run(PropertyApplication.class, args);
}
}
. @ConfigurationProperties
@Value在每个类中获取属性配置值的做法,其实是不推荐的。
一般在企业项目开发中,不会使用那么杂乱无章的写法而且维护也麻烦,通常会一次性读取一个 Java 配置类,然后在需要使用的地方直接引用这个类就可以多次访问了,方便维护,示例如下:
首先,在application.properties文件里定义好参数变量。
config.name=demo_1
config.value=demo_value_1
然后,创建一个 Java 配置类,将参数变量注入即可!
@Component
@ConfigurationProperties(prefix = "config")
public class Config {
public String name;
public String value;
//...get、set
}
. @PropertySource
这个注解是用来读取我们自定义的配置文件的,比如导入test.properties和bussiness.properties两个配置文件,用法如下:
@SpringBootApplication
@PropertySource(value = {"test.properties","bussiness.properties"})
public class PropertyApplication {
public static void main(String[] args) {
SpringApplication.run(PropertyApplication.class, args);
}
}
. @ImportResource
用来加载 xml 配置文件,比如导入自定义的aaa.xml文件,用法如下:
@ImportResource(locations = "classpath:aaa.xml")
@SpringBootApplication
public class PropertyApplication {
public static void main(String[] args) {
SpringApplication.run(PropertyApplication.class, args);
}
- 异常处理相关注解
. @ControllerAdvice和@ExceptionHandler
通常组合使用,用于处理全局异常,示例代码如下:
@ControllerAdvice
@Configuration
@Slf4j
public class GlobalExceptionConfig {
private static final Integer GLOBAL_ERROR_CODE = 500;
@ExceptionHandler(value = Exception.class)
@ResponseBody
public void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
log.error("【统一异常处理器】", e);
ResultMsg<Object> resultMsg = new ResultMsg<>();
resultMsg.setCode(GLOBAL_ERROR_CODE);
if (e instanceof CommonException) {
CommonException ex = (CommonException) e;
if(ex.getErrCode() != 0) {
resultMsg.setCode(ex.getErrCode());
}
resultMsg.setMsg(ex.getErrMsg());
}else {
resultMsg.setMsg(CommonErrorMsg.SYSTEM_ERROR.getMessage());
}
WebUtil.buildPrintWriter(response, resultMsg);
}
}
- 测试相关注解
. @ActiveProfiles
一般作用于测试类上, 用于声明生效的 Spring 配置文件,比如指定application-dev.properties配置文件。
. @RunWith和@SpringBootTest一般作用于测试类上, 用于单元测试用,示例如下:
@ActiveProfiles("dev")
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestJunit {
@Test
public void executeTask() {
//测试...
}
}