跳到主要内容

Spring 速查表

本文档提供 Spring Framework 常用配置、注解和代码片段的快速参考。

核心注解

组件注解

注解说明示例
@Component通用组件@Component
@Repository持久层组件@Repository
@Service业务层组件@Service
@Controller控制器组件@Controller
@RestControllerREST 控制器@RestController
@Configuration配置类@Configuration
@BeanBean 定义方法@Bean

依赖注入

注解说明示例
@Autowired自动装配@Autowired
@Qualifier指定 Bean 名称@Qualifier("userService")
@Primary默认 Bean@Primary
@ResourceJSR-250 注入@Resource
@InjectJSR-330 注入@Inject
@Value属性注入@Value("{app.name}")
@Lazy延迟加载@Lazy

作用域

注解说明
@Scope("singleton")单例(默认)
@Scope("prototype")原型
@Scope("request")请求作用域
@Scope("session")会话作用域
@Scope("application")应用作用域

条件化

注解说明
@Conditional条件化 Bean
@ConditionalOnProperty属性条件
@ConditionalOnClass类存在条件
@ConditionalOnMissingBeanBean 不存在条件
@Profile环境配置

IOC 容器

配置类

@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:application.properties")
public class AppConfig {

@Bean
@Primary
public DataSource dataSource() {
return new HikariDataSource();
}

@Bean
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public CacheManager cacheManager() {
return new RedisCacheManager();
}
}

获取 Bean

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

UserService userService = context.getBean(UserService.class);
UserService userService = context.getBean("userService", UserService.class);
Map<String, UserService> beans = context.getBeansOfType(UserService.class);

Bean 生命周期

@Service
public class UserService implements InitializingBean, DisposableBean {

@PostConstruct
public void init() {
}

@Override
public void afterPropertiesSet() {
}

@PreDestroy
public void cleanup() {
}

@Override
public void destroy() {
}
}

AOP

切面定义

@Aspect
@Component
@Order(1)
public class LoggingAspect {

@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}

@Before("serviceLayer()")
public void before(JoinPoint joinPoint) {
}

@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
}

@AfterThrowing(pointcut = "serviceLayer()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
}

@Around("serviceLayer()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
return joinPoint.proceed();
}
}

切入点表达式

表达式说明
execution(* com.example.service.*.*(..))匹配 service 包下所有方法
execution(* com.example.service..*.*(..))匹配 service 包及子包下所有方法
execution(public * *(..))匹配所有 public 方法
execution(* set*(..))匹配所有 setter 方法
within(com.example.service.*)匹配包内所有类型
@annotation(com.example.Log)匹配带注解的方法
bean(userService)匹配特定 Bean

事务管理

声明式事务

@Service
public class UserService {

@Transactional
public void save(User user) {
}

@Transactional(readOnly = true)
public User findById(Long id) {
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(User user) {
}

@Transactional(isolation = Isolation.READ_COMMITTED)
public void update(User user) {
}

@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
}

@Transactional(timeout = 30)
public void longOperation() {
}
}

传播行为

传播行为说明
REQUIRED有事务则加入,无则新建(默认)
SUPPORTS有事务则加入,无则非事务执行
MANDATORY必须在事务中执行
REQUIRES_NEW总是新建事务
NOT_SUPPORTED非事务方式执行
NEVER非事务方式执行,有事务则异常
NESTED嵌套事务

隔离级别

隔离级别脏读不可重复读幻读
READ_UNCOMMITTED
READ_COMMITTED×
REPEATABLE_READ××
SERIALIZABLE×××

数据访问

JdbcTemplate

@Repository
public class UserDao {

@Autowired
private JdbcTemplate jdbcTemplate;

public User findById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class), id);
}

public List<User> findAll() {
return jdbcTemplate.query(
"SELECT * FROM users",
new BeanPropertyRowMapper<>(User.class));
}

public int save(User user) {
return jdbcTemplate.update(
"INSERT INTO users(name, email) VALUES(?, ?)",
user.getName(), user.getEmail());
}

public Long saveAndGetId(User user) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO users(name, email) VALUES(?, ?)",
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, user.getName());
ps.setString(2, user.getEmail());
return ps;
}, keyHolder);
return keyHolder.getKey().longValue();
}
}

NamedParameterJdbcTemplate

@Repository
public class UserDao {

@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;

public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = :id";
MapSqlParameterSource params = new MapSqlParameterSource("id", id);
return jdbcTemplate.queryForObject(sql, params,
new BeanPropertyRowMapper<>(User.class));
}

public List<User> findByIds(List<Long> ids) {
String sql = "SELECT * FROM users WHERE id IN (:ids)";
MapSqlParameterSource params = new MapSqlParameterSource("ids", ids);
return jdbcTemplate.query(sql, params,
new BeanPropertyRowMapper<>(User.class));
}
}

Spring MVC

控制器

@RestController
@RequestMapping("/api/users")
public class UserController {

@GetMapping
public List<User> list() {
return userService.findAll();
}

@GetMapping("/{id}")
public User detail(@PathVariable Long id) {
return userService.findById(id);
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User create(@Valid @RequestBody UserDTO dto) {
return userService.create(dto);
}

@PutMapping("/{id}")
public User update(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}

@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long id) {
userService.delete(id);
}

@GetMapping("/search")
public List<User> search(
@RequestParam String name,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return userService.search(name, PageRequest.of(page, size));
}
}

参数注解

注解说明
@PathVariable路径变量
@RequestParam请求参数
@RequestBody请求体
@RequestHeader请求头
@CookieValueCookie 值
@ModelAttribute表单绑定
@Valid数据验证

异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse("NOT_FOUND", ex.getMessage()));
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return ResponseEntity.badRequest()
.body(new ErrorResponse("VALIDATION_ERROR", message));
}
}

缓存

缓存注解

@Service
@CacheConfig(cacheNames = "users")
public class UserService {

@Cacheable(key = "#id")
public User findById(Long id) {
return userDao.findById(id);
}

@Cacheable(key = "#email", unless = "#result == null")
public User findByEmail(String email) {
return userDao.findByEmail(email);
}

@CachePut(key = "#user.id")
public User update(User user) {
return userDao.save(user);
}

@CacheEvict(key = "#id")
public void delete(Long id) {
userDao.deleteById(id);
}

@CacheEvict(allEntries = true)
public void refreshAll() {
}
}

任务调度

定时任务

@Component
public class ScheduledTasks {

@Scheduled(fixedRate = 5000)
public void everyFiveSeconds() {
}

@Scheduled(fixedDelay = 5000)
public void afterCompletion() {
}

@Scheduled(cron = "0 0 12 * * ?")
public void atNoon() {
}

@Scheduled(initialDelay = 10000, fixedRate = 60000)
public void withInitialDelay() {
}
}

异步任务

@Service
public class EmailService {

@Async
public void sendEmail(String to, String content) {
}

@Async
public CompletableFuture<String> sendAsync(String to, String content) {
return CompletableFuture.completedFuture("sent");
}
}

事件

事件定义与使用

public class UserCreatedEvent extends ApplicationEvent {
private final Long userId;

public UserCreatedEvent(Object source, Long userId) {
super(source);
this.userId = userId;
}
}

@Service
public class UserService {
@Autowired
private ApplicationEventPublisher publisher;

public void create(User user) {
publisher.publishEvent(new UserCreatedEvent(this, user.getId()));
}
}

@Component
public class UserEventListener {
@EventListener
public void onUserCreated(UserCreatedEvent event) {
}

@Async
@EventListener
public void asyncHandler(UserCreatedEvent event) {
}

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommit(UserCreatedEvent event) {
}
}

配置属性

属性绑定

@Configuration
@ConfigurationProperties(prefix = "app")
@Data
public class AppProperties {
private String name;
private int timeout;
private List<String> servers;
}

@Configuration
@ConfigurationProperties(prefix = "app.datasource")
@Data
public class DataSourceProperties {
private String url;
private String username;
private String password;
}

application.properties:

app.name=MyApp
app.timeout=30000
app.servers[0]=server1
app.servers[1]=server2
app.datasource.url=jdbc:mysql://localhost:3306/test
app.datasource.username=root
app.datasource.password=secret

常用配置

数据源配置

@Configuration
public class DataSourceConfig {

@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public DataSource dataSource() {
return new HikariDataSource();
}

@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

Web MVC 配置

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("/static/");
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static/**");
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
}