What is `@Service` does?

26 篇文章 0 订阅
11 篇文章 0 订阅

@ServiceSpring注解,标记服务(业务层)组件。它属于Spring的组件扫描依赖注入机制的一部分, Spring IoC容器在启动时自动检测并实例化这个类,并自动将其他需要的Bean注入到该服务类中(DI)。

业务层主要负责:核心业务处理逻辑,例如数据操作、复杂的计算、事务管理等。

在这里插入图片描述

使用样例

使用@Autowired注解进行依赖注入

import org.springframework.stereotype.Service;

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findUserById(Long id) {
        // 这里调用userRepository的方法实现用户查询逻辑
        return userRepository.findById(id);
    }
}

带有多个业务方法的服务类

import org.springframework.stereotype.Service;

@Service
public class OrderService {

    private ProductService productService;
    private InventoryService inventoryService;
    
    @Autowired
    public OrderService(ProductService productService, InventoryService inventoryService) {
        this.productService = productService;
        this.inventoryService = inventoryService;
    }

    public Order createOrder(OrderRequest orderRequest) {
        // 从请求中获取产品ID和数量
        Long productId = orderRequest.getProductId();
        int quantity = orderRequest.getQuantity();

        // 使用productService获取产品信息
        Product product = productService.getProductById(productId);

        // 检查库存是否充足
        if (!inventoryService.isStockAvailable(product.getId(), quantity)) {
            throw new InsufficientStockException("Not enough stock for product ID: " + productId);
        }

        // ...

        return order;
    }

    // 其他业务逻辑方法...
}

使用@Qualifier注解进行精确依赖注入

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class EmailNotificationService {

    private final NotificationProvider notificationProvider;

    @Autowired
    public EmailNotificationService(@Qualifier("smtpEmailProvider") NotificationProvider notificationProvider) {
        this.notificationProvider = notificationProvider;
    }

    public void sendNotification(User user, String message) {
        notificationProvider.send(user.getEmail(), message);
    }
}

@Service("smtpEmailProvider")
public class SmtpEmailProvider implements NotificationProvider {
    // 实现发送电子邮件的逻辑...
}

@Service("smsNotificationProvider")
public class SmsNotificationProvider implements NotificationProvider {
    // 实现发送短信的逻辑...
}

使用事务管理的@Service类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class AccountingService {

    private final TransactionRepository transactionRepository;
    private final AccountRepository accountRepository;

    @Autowired
    public AccountingService(TransactionRepository transactionRepository, AccountRepository accountRepository) {
        this.transactionRepository = transactionRepository;
        this.accountRepository = accountRepository;
    }

    @Transactional
    public void processPayment(Long fromAccountId, Long toAccountId, double amount) {
        // 更新账户余额
        Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow();
        Account toAccount = accountRepository.findById(toAccountId).orElseThrow();

        fromAccount.debit(amount);
        toAccount.credit(amount);

        // 保存账户更改
        accountRepository.save(fromAccount);
        accountRepository.save(toAccount);

        // 记录交易
        Transaction transaction = new Transaction(fromAccount, toAccount, amount);
        transactionRepository.save(transaction);
    }
}

使用缓存优化服务性能

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    @Cacheable(value = "products", key = "#id")
    public Product getProductById(Long id) {
        // 查询数据库或其他数据源获取产品信息
        return productRepository.findById(id).orElseThrow(() -> new NotFoundException("Product not found with ID: " + id));
    }

    @CacheEvict(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        // 更新产品信息到数据库
        return productRepository.save(product);
    }

    @CacheEvict(value = "products", allEntries = true)
    public void clearProductCache() {
        System.out.println("Product cache cleared.");
    }
}

异步处理任务的服务类

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncEmailService {

    @Async
    public void sendWelcomeEmail(User user) {
        // 这里调用邮件发送API或库,发送欢迎邮件给用户
        emailService.send(user.getEmail(), "Welcome to our platform!", createWelcomeMessage(user));
    }

    private String createWelcomeMessage(User user) {
        // 创建欢迎邮件的内容
        return "Dear " + user.getName() + ",\n\nWelcome to our platform!...";
    }
}

使用自定义注解和切面实现服务日志记录

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;

@Aspect
@Service
public class LoggingService {

    @Around("@annotation(Loggable)")
    public Object logMethodExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        
        // 执行原方法
        Object result = joinPoint.proceed();

        long executionTime = System.currentTimeMillis() - start;
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String className = signature.getDeclaringType().getSimpleName();
        String methodName = signature.getName();

        System.out.printf("Method [%s.%s()] executed in %d ms%n", className, methodName, executionTime);

        return result;
    }
}

// 自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {
}


import org.springframework.stereotype.Service;
import com.example.annotation.Loggable; // 引入自定义注解

@Service
public class UserService {

    @Loggable
    public User getUserById(Long id) {
        // 获取用户逻辑...
        return userRepository.findById(id).orElseThrow(() -> new NotFoundException("User not found with ID: " + id));
    }

    // 其他业务逻辑方法...
}

使用@CacheEvict注解清除缓存

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    // 缓存产品信息
    @Cacheable(value = "products", key = "#id")
    public Product getProductById(Long id) {
        return productRepository.findById(id).orElseThrow(() -> new NotFoundException("Product not found with ID: " + id));
    }

    // 更新产品后清除相关缓存
    @CacheEvict(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        return productRepository.save(product);
    }
}

服务类中的事件监听与发布

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    private final ApplicationEventPublisher eventPublisher;

    @Autowired
    public OrderService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void placeOrder(Order order) {
        // 处理订单创建逻辑...

        // 订单创建成功后发布一个事件
        eventPublisher.publishEvent(new OrderPlacedEvent(this, order));
    }

    // 监听订单创建事件
    @EventListener
    public void handleOrderPlacedEvent(OrderPlacedEvent event) {
        Order order = event.getOrder();
        // 在这里执行订单创建后的附加操作,例如发送通知邮件或更新统计信息...
    }
}

// 自定义事件类
public class OrderPlacedEvent extends ApplicationEvent {
    private final Order order;

    public OrderPlacedEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }

    public Order getOrder() {
        return order;
    }
}

使用@Scheduled注解实现定时任务

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledTaskService {

    @Scheduled(cron = "0 0 * * * ?") // 每天凌晨执行一次
    public void dailyCleanup() {
        System.out.println("Executing Daily Cleanup Task at " + LocalDateTime.now());

        // 清理或归档过期数据的逻辑...
    }

    @Scheduled(fixedRate = 60000) // 每隔1分钟执行一次
    public void monitorSystemStatus() {
        System.out.println("Monitoring System Status at " + LocalDateTime.now());

        // 监控系统状态并记录日志的逻辑...
    }
}

服务类中的异常处理

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User getUserById(Long id) {
        return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found with ID: " + id));
    }

    // 异常处理器方法
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

class ResourceNotFoundException extends RuntimeException {
    // ...
}

使用@Validated和@Valid进行参数验证

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderService {

    private final OrderRepository orderRepository;
    private final PaymentService paymentService;

    @Autowired
    public OrderService(OrderRepository orderRepository, PaymentService paymentService) {
        this.orderRepository = orderRepository;
        this.paymentService = paymentService;
    }

    @Transactional
    public void processOrder(Order order, CreditCard creditCard) {
        // 保存订单
        orderRepository.save(order);

        // 处理支付
        paymentService.charge(creditCard, order.getTotalAmount());

        // 更新订单状态(假设这是另一个数据库操作)
        order.setStatus(OrderStatus.PAID);
        orderRepository.save(order);
    }
}

使用@PostConstruct和@PreDestroy注解进行初始化和销毁操作

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Service;

@Service
public class ConfigurationService {

    private final DatabaseConfig databaseConfig;
    
    @Autowired
    public ConfigurationService(DatabaseConfig databaseConfig) {
        this.databaseConfig = databaseConfig;
    }

	# 当Spring容器完成对ConfigurationService实例的创建和依赖注入后,
	# 会自动调用带有 @PostConstruct 注解的方法,用于执行服务初始化逻辑,
	# 如初始化数据库连接池或加载默认参数。
    @PostConstruct
    public void init() {
        System.out.println("Initializing Configuration Service...");
        
        // 初始化配置,例如设置数据库连接池大小、加载默认参数等
        databaseConfig.initializeConnectionPool();
        loadDefaultParameters();
    }

    private void loadDefaultParameters() {
        // 加载并设置默认的系统参数
        // ...
    }

	# 当Spring容器准备关闭或者删除 ConfigurationService 实例之前,会调用带有 @PreDestroy 注解的方法,
	# 以执行清理资源的操作,比如关闭数据库连接、清理缓存数据等。
	# 这样可以确保在应用停止或服务实例被替换时资源能够正确地回收和释放。
    @PreDestroy
    public void cleanup() {
        System.out.println("Cleaning up Configuration Service...");

        // 释放资源,关闭数据库连接,清理缓存等
        databaseConfig.closeConnectionPool();
        clearCachedData();
    }

    private void clearCachedData() {
        // 清理缓存中的数据
        // ...
    }
}

使用@Async注解实现异步任务

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncEmailService {

    @Async
    public void sendWelcomeEmail(User user) {
        // 异步发送欢迎邮件逻辑...
        System.out.println("Sending welcome email to " + user.getEmail() + " asynchronously...");
        // 实际代码中会调用电子邮件服务进行邮件发送
    }
}

@Configuration
@EnableAsync
public class AsyncConfig {
    // 可以在这里配置线程池参数,例如:
    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(20);
        executor.initialize();
        return executor;
    }
}

使用@Value注解注入属性值

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class ConfigurableService {

    @Value("${app.max.concurrent.requests}")
    private int maxConcurrentRequests;

    public void processRequest() {
        // 根据maxConcurrentRequests设置限制并发请求的数量
        if (activeRequests.get() < maxConcurrentRequests) {
            // 执行处理逻辑...
            activeRequests.incrementAndGet();
            try {
                // 请求处理代码...
            } finally {
                activeRequests.decrementAndGet();
            }
        } else {
            System.out.println("Too many concurrent requests, please try again later.");
        }
    }

    // 假设activeRequests是一个AtomicInteger类型的成员变量,用于跟踪当前活跃的请求数量
}

使用@Profile注解实现环境切换

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("dev")
public class DevDatabaseService implements DatabaseService {

    @Override
    public void connect() {
        System.out.println("Connecting to the development database...");
        // 连接到开发环境的数据库
    }
}

@Service
@Profile("prod")
public class ProdDatabaseService implements DatabaseService {

    @Override
    public void connect() {
        System.out.println("Connecting to the production database...");
        // 连接到生产环境的数据库
    }
}

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值