【Spring Framework】使用完全注解方式开发

Spring Framework 是一个非常灵活且强大的 Java 企业级开发框架,它允许开发人员以多种方式进行配置和开发。在现代 Java 开发中,使用完全注解的方式来进行配置和开发已经成为趋势,这种方式能够减少 XML 配置文件的使用,使代码更加简洁和易于维护。

在本文中,我将详细介绍如何使用 Spring 的注解配置来进行完全注解化开发,包括如何定义 Bean、管理依赖注入、配置数据库、实现 AOP、处理事务等方面。

1. 完全注解配置的优点

完全注解配置有许多优点:

  • 减少 XML 依赖:不再需要繁琐的 XML 配置文件,所有配置都可以在 Java 类中通过注解完成。
  • 提高可读性和可维护性:配置更加紧凑,易于阅读和维护。
  • 类型安全:利用 Java 类型系统进行配置,减少配置错误。
  • 更好的 IDE 支持:IDE 对注解提供了良好的自动补全和重构支持。
  • 便于测试:配置类可以通过单元测试进行独立验证。

2. 基本注解和概念

在 Spring 中,注解可以用来定义和配置 Bean,以及实现自动装配、事务管理等功能。以下是一些常用的注解:

  • @Configuration:用于定义配置类,该类可以替代 XML 配置文件。
  • @Bean:用于定义 Bean,返回的对象会被注册为 Spring 应用上下文中的一个 Bean。
  • @Component@Service@Repository@Controller:用于自动扫描并注册为 Spring Bean,分别用于不同层次的组件(通用组件、服务层、持久层和控制层)。
  • @Autowired:用于自动装配 Bean,可以作用于字段、构造器或方法上。
  • @Qualifier:与 @Autowired 一起使用,用于明确指定注入的 Bean。
  • @Value:用于注入属性值。
  • @PropertySource:指定外部属性文件的位置。
  • @EnableTransactionManagement:启用注解驱动的事务管理。
  • @Transactional:用于标记事务边界。
  • @EnableAspectJAutoProxy:启用基于注解的 AOP 支持。

3. 创建一个简单的 Spring 项目

为了演示完全注解化配置开发,我们将创建一个简单的 Spring 项目,包括以下几个模块:

  1. 配置类。
  2. 数据库连接和数据访问层。
  3. 服务层。
  4. 控制器层。
  5. AOP 和事务管理。

3.1 项目结构

src/main/java
|-- com.example|-- config|-- AppConfig.java|-- DataSourceConfig.java|-- WebConfig.java|-- model|-- User.java|-- repository|-- UserRepository.java|-- UserRepositoryImpl.java|-- service|-- UserService.java|-- UserServiceImpl.java|-- controller|-- UserController.java|-- aop|-- LoggingAspect.java|-- Application.java

3.2 配置类

3.2.1 AppConfig.java

AppConfig 是主配置类,启用组件扫描和其他核心功能。

package com.example.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@ComponentScan(basePackages = "com.example") // 扫描com.example包下的所有组件
@EnableTransactionManagement // 启用事务管理
@EnableAspectJAutoProxy // 启用AOP代理
@PropertySource("classpath:application.properties") // 加载属性文件
public class AppConfig {// AppConfig 是项目的核心配置类,不包含具体的 Bean 定义
}
3.2.2 DataSourceConfig.java

DataSourceConfig 用于配置数据源和 JdbcTemplate。

package com.example.config;import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {BasicDataSource dataSource = new BasicDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC");dataSource.setUsername("root");dataSource.setPassword("password");// 可选配置dataSource.setInitialSize(5);dataSource.setMaxTotal(10);dataSource.setMaxIdle(5);dataSource.setMinIdle(2);return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
3.2.3 WebConfig.java

如果你正在使用 Spring MVC,则可以使用 WebConfig 来配置 DispatcherServlet、视图解析器等。

package com.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;@Configuration
@EnableWebMvc // 启用Spring MVC
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");registry.viewResolver(resolver);}// 可以在这里添加更多的 MVC 配置
}

3.3 模型类

创建一个简单的 User 模型类。

package com.example.model;public class User {private int id;private String name;private String email;// 构造函数public User() {}public User(int id, String name, String email) {this.id = id;this.name = name;this.email = email;}// Getter 和 Setterpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", email='" + email + '\'' +'}';}
}

3.4 数据访问层

创建 UserRepository 接口和 UserRepositoryImpl 实现类,使用 JdbcTemplate 进行数据库操作。

3.4.1 UserRepository.java
package com.example.repository;import com.example.model.User;
import java.util.List;public interface UserRepository {void insertUser(User user);void updateUser(User user);void deleteUser(int id);User findUserById(int id);List<User> findAllUsers();
}
3.4.2 UserRepositoryImpl.java
package com.example.repository;import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@Repository
public class UserRepositoryImpl implements UserRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void insertUser(User user) {String sql = "INSERT INTO users (name, email) VALUES (?, ?)";jdbcTemplate.update(sql, user.getName(), user.getEmail());}@Overridepublic void updateUser(User user) {String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?";jdbcTemplate.update(sql, user.getName(), user.getEmail(), user.getId());}@Overridepublic void deleteUser(int id) {String sql = "DELETE FROM users WHERE id = ?";jdbcTemplate.update(sql, id);}@Overridepublic User findUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";return jdbcTemplate.queryForObject(sql, new Object[]{id}, this::mapRowToUser);}@Overridepublic List<User> findAllUsers() {String sql = "SELECT * FROM users";return jdbcTemplate.query(sql, this::mapRowToUser);}private User mapRowToUser(ResultSet rs, int rowNum) throws SQLException {return new User(rs.getInt("id"),rs.getString("name"),rs.getString("email"));}
}

3.5 服务层

创建 UserService 接口和 UserServiceImpl 实现类,使用注解配置事务管理。

3.5.1 UserService.java
package com.example.service;import com.example.model.User;import java.util.List;public interface UserService {void registerUser(User user);void modifyUser(User user);void removeUser(int id);User getUserById(int id);List<User> listAllUsers();
}
3.5.2 UserServiceImpl.java
package com.example.service;import com.example.model.User;
import com.example.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Override@Transactionalpublic void registerUser(User user) {userRepository.insertUser(user);}@Override@Transactionalpublic void modifyUser(User user) {userRepository.updateUser(user);}@Override@Transactionalpublic void removeUser(int id) {userRepository.deleteUser(id);}@Overridepublic User getUserById(int id) {return userRepository.findUserById(id);}@Overridepublic List<User> listAllUsers() {return userRepository.findAllUsers();}
}

3.6 控制器层

在控制器层中使用 @Controller 注解定义 Web 控制器。这里,我们将创建一个简单的控制器来展示如何处理请求。

3.6.1 UserController.java
package com.example.controller;import com.example.model.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import java.util.List;@Controller
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic String listUsers(Model model) {List<User> users = userService.listAllUsers();model.addAttribute("users", users);return "user/list"; // 视图名称}@GetMapping("/{id}")public String getUser(@PathVariable int id, Model model) {User user = userService.getUserById(id);model.addAttribute("user", user);return "user/detail";}@PostMappingpublic String createUser(@ModelAttribute User user) {userService.registerUser(user);return "redirect:/users";}@PutMapping("/{id}")public String updateUser(@PathVariable int id, @ModelAttribute User user) {user.setId(id);userService.modifyUser(user);return "redirect:/users/" + id;}@DeleteMapping("/{id}")public String deleteUser(@PathVariable int id) {userService.removeUser(id);return "redirect:/users";}
}

3.7 AOP 切面编程

在 Spring 中,AOP(Aspect-Oriented Programming)允许我们将横切关注点(如日志记录、事务管理、权限检查等)从业务逻辑中分离出来。这里,我们将创建一个简单的日志切面。

3.7.1 LoggingAspect.java
package com.example.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Before("execution(* com.example.service.UserService.*(..))")public void logBefore(JoinPoint joinPoint) {logger.info("执行方法: " + joinPoint.getSignature().getName());}@AfterReturning(pointcut = "execution(* com.example.service.UserService.*(..))", returning = "result")public void logAfterReturning(JoinPoint joinPoint, Object result) {logger.info("方法返回: " + joinPoint.getSignature().getName() + ",返回值: " + result);}
}

3.8 启动类

最后,创建一个启动类来运行 Spring 应用程序。

3.8.1 Application.java
package com.example;import com.example.config.AppConfig;
import com.example.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Application {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);UserService userService = context.getBean(UserService.class);// 添加用户userService.registerUser(new User(1, "Alice", "alice@example.com"));// 列出所有用户userService.listAllUsers().forEach(System.out::println);// 查找用户User user = userService.getUserById(1);System.out.println("查找到的用户: " + user);// 更新用户user.setName("Alice Updated");userService.modifyUser(user);// 删除用户userService.removeUser(1);context.close();}
}

4. 总结

本文介绍了如何使用 Spring 完全注解化的方式来进行开发。通过使用注解,我们可以减少 XML 配置文件的使用,使项目的配置更加直观和简洁。以下是本文的主要内容:

  • 配置类:使用 @Configuration@Bean@ComponentScan 等注解定义配置类。
  • 数据库配置:使用 DataSourceJdbcTemplate 以及 @Autowired 自动装配数据源。
  • 服务层和控制器层:使用 @Service@Controller 注解定义业务逻辑和控制器,并使用 @Autowired 注入依赖。
  • AOP 和事务管理:通过 @Aspect@Transactional 注解实现日志记录和事务管理。

这种完全注解化的开发方式在 Spring Boot 中得到了进一步的增强和推广,成为现代 Java 开发的主流方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/50244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高级及架构师高频面试题

一、微服务多节点批量应该怎么设计&#xff1f; 1、异步任务分类&#xff1a; 周期性定时任务调度任务批量任务 2、需要考虑并解决的问题&#xff1a; 2.1、避免同一任务同时被多个节点捞取。 1&#xff09;数据库的行级锁 2&#xff09;redis分布式锁 3&#xff09;quartz…

【运维笔记】数据库无法启动,数据库炸后备份恢复数据

事情起因 在做docker作业的时候&#xff0c;把卷映射到了宿主机原来的mysql数据库目录上&#xff0c;宿主机原来的mysql版本为8.0&#xff0c;docker容器版本为5.6&#xff0c;导致翻车。 具体操作 备份目录 将/var/lib/mysql备份到~/mysql_backup&#xff1a;cp /var/lib/…

Multiview LM-ICP 配准算法

Multiview LM-ICP 配准算法针对一些大型的物体&#xff08;比如建筑物&#xff09;或者需要精细化建模的物体&#xff08;比如某个文物&#xff09;&#xff0c;仅仅进行成对的配准难以还原物体的全貌和细节。所以&#xff0c;多个视角的配准十分关键。 多视角的配准存在以下两…

[STM32]FlyMcu同时烧写BootLoader和APP文件-HEX文件组成

目录 一、前言 二、HEX文件的格式 三、组合HEX文件 四、使用FlyMcu烧录 一、前言 如题&#xff0c;BootLoader每次烧写都是全部擦除&#xff0c;当我们烧写APP程序的时候&#xff0c;BootLoader程序将不复存在&#xff0c;很多开发者或许只有USB转TTL模块&#xff0c;没有其…

grep命令搜索部分命令

首先 然后可以输入&#xff5c;以及grep命令 比如 bjobs| grep "3075*"bjobs| grep "3075"这个结果是这样的&#xff0c;

mysql的存储过程:

mysql的存储过程&#xff1a; 存储过程的概念&#xff1a; 完成特点功能的sql语句的集合。把定义好的sql集合在一个特定的sql的函数当中 每次执行调用函数即可&#xff0c;还可以实现传参的调用 存储过程的语法&#xff1a; delimiter $$ #delimiter 开始和结束的语法&…

MYSQL 第四次作业

任务要求&#xff1a; 具体操作&#xff1a; 新建数据库&#xff1a; mysql> CREATE DATABASE mydb15_indexstu; Query OK, 1 row affected (0.01 sec) mysql> USE mydb15_indexstu; Database changed 新建表&#xff1a; mysql> CREATE TABLE student( ->…

遇到总条数count(*)返回不了数据

文章目录 前提1.准备数据1.1 建表语句1.2 插入数据 2.程序代码3.返回结果与分析4.验证 前提 获取h_user表中count(*)字段的值打印出来&#xff0c;打印出来是0&#xff0c;数据库中执行sql返回不是0。端点调试找到原因。下面先把数据库表数据及程序贴出来。 1.准备数据 1.1 …

CSS技巧专栏:一日一例 12 -纯CSS实现边框上下交错的按钮特效

CSS技巧专栏&#xff1a;一日一例 12 -纯CSS实现边框上下交错的按钮特效 大家好&#xff0c;今天我们来做一个上下边框交错闪动的按钮特效。 本例图片 案例分析 虽说这按钮给人的感觉就是上下两个边框交错变换了位置&#xff0c;但我们都知道border是没法移动的。那么这个按…

【无标KaiwuDB CTO 魏可伟:差异化创新,面向行业的多模架构题】

2024年7月16日&#xff0c;KaiwuDB CTO 魏可伟受邀于 2024 可信数据库发展大会主论坛发表演讲《多模一库 —— KaiwuDB 的现代数据库架构探索》&#xff0c;以下是演讲精华实录。 多模数据库 是顺应时代发展与融合趋势的产物 数据模型最早始于网状模型和层次模型&#xff0c;…

Spark实时(五):InputSource数据源案例演示

文章目录 InputSource数据源案例演示 一、​​​​​​​File Source 1、读取text文件 2、读取csv文件 3、读取json文件 二、Socket Source 三、Rate Source InputSource数据源案例演示 在Spark2.0版本之后&#xff0c;DataFrame和Dataset可以表示静态有边界的数据&am…

移动式气象站:便携科技的天气守望者

在科技日新月异的今天&#xff0c;我们身边的许多设备都在向着更加智能化、便携化的方向发展。而在气象观测领域&#xff0c;移动式气象站的出现&#xff0c;不仅改变了传统气象观测的固有模式&#xff0c;更以其灵活性和实时性&#xff0c;在气象监测、灾害预警等领域发挥着越…

MySQL练习05

题目 步骤 触发器 use mydb16_trigger; #使用数据库create table goods( gid char(8) primary key, name varchar(10), price decimal(8,2), num int);create table orders( oid int primary key auto_increment, gid char(10) not null, name varchar(10), price decima…

基于python的BP神经网络红酒品质分类预测模型

1 导入必要的库 import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from tensorflow.keras.models import Sequential from tenso…

NET8部署Kestrel服务HTTPS深入解读TLS协议之Certificate证书

Certificate证书 Certificate称为数字证书。数字证书是一种证明身份的电子凭证&#xff0c;它包含一个公钥和一些身份信息&#xff0c;用于验证数字签名和加密通信。数字证书在网络通信、电子签名、认证授权等场景中都有广泛应用。其特征如下&#xff1a; 由权威机构颁发&…

跟李沐学AI:池化层

目录 二维最大池化 填充、步幅和多个通道 平均池化层 池化层总结 二维最大池化 返回滑动窗口中的最大值。 图为池化窗口形状为 22 的最大池化层。着色部分是第一个输出元素&#xff0c;以及用于计算这个输出的输入元素: max(0,1,3,4)4。池化层与卷积层类似&#xff0c;不断…

Spark核心知识要点(八)Shuffle配置调优

1、Shuffle优化配置 -spark.shuffle.file.buffer 默认值&#xff1a;32k参数说明&#xff1a;该参数用于设置shuffle write task的BufferedOutputStream的buffer缓冲大小。将数据写到磁盘文件之前&#xff0c;会先写入buffer缓冲中&#xff0c;待缓冲写满之后&#xff0c;才会…

Linux中,MySQL的用户管理

MySQL库中的表及其作用 user表 User表是MySQL中最重要的一个权限表&#xff0c;记录允许连接到服务器的帐号信息&#xff0c;里面的权限是全局级的。 db表和host表 db表和host表是MySQL数据中非常重要的权限表。db表中存储了用户对某个数据库的操作权限&#xff0c;决定用户…

单元测试的最佳实践

整体架构 合适的架构可以提升可测试性。比如菱形对称架构的模块化和解耦特性使得系统各个部分可以独立进行单元测试。这不仅提高了测试的效率&#xff0c;还能够减少测试的依赖性&#xff0c;提高测试准确性。 代码设计 代码设计和可测试性有密切关联。强烈建议一个方法的代码行…

Android 15 适配整理——实践版

背景 谷歌发布Android 15后&#xff0c;国内的手机厂商迅速行动&#xff0c;开始了新系统的适配工作。小米、OPPO、vivo和联想等金标联盟成员联合发布了适配公告&#xff0c;督促APP开发者在2024年8月31日前完成适配工作&#xff0c;否则将面临搜索标签提示、应用降级、分机型…