Spring框架中的AOP与动态代理解析

需积分: 10 0 下载量 182 浏览量 更新于2024-08-26 收藏 20KB MD 举报
"Spring系列——AOP" 在JavaEE开发中,Spring框架的AOP(面向切面编程)是一个重要的组成部分,它允许开发者在不修改原有业务逻辑的情况下,添加如事务管理、日志记录等横切关注点。本篇将探讨Spring AOP的基础,包括静态代理设计模式以及Spring的动态代理。 ### 静态代理设计模式 #### 1. 为什么需要代理设计模式? 在传统的JavaEE三层架构中,Service层是最关键的一层,因为它负责业务逻辑的处理和数据访问对象(DAO)的调用。Service层的代码通常包含两部分:核心功能(业务运算、DAO调用)和额外功能(如事务管理、日志记录、性能监控)。将额外功能混入Service层对于调用者(如Controller)来说是必要的,但从软件设计的角度来看,这种耦合不利于代码的维护和扩展。 #### 2. 代理设计模式概念 代理设计模式旨在通过代理类为原始类增加额外的功能,以提高代码的可维护性和解耦。代理类不仅实现了原始类的功能,还包含了额外的功能,并且原始类与代理类都实现了同一个接口。 #### 3. 静态代理的实现与问题 静态代理是通过手动为每个原始类编写对应的代理类来实现的。例如,对于`UserService`,我们会创建一个`UserServiceProxy`,它实现`UserService`接口并添加额外功能。然而,这种方法存在两个主要问题:一是随着原始类数量的增加,代理类的文件数量也会增加,不利于项目的管理;二是当需要修改或添加额外功能时,需要逐个修改所有代理类,维护成本高。 ### Spring的动态代理 #### 1. Spring动态代理概念 Spring的动态代理解决了静态代理的这些问题。它可以在运行时动态地创建代理类,不需要为每个原始类单独编写代理类。Spring支持两种动态代理方式:JDK动态代理和CGLIB代理。 - **JDK动态代理**:基于接口实现,如果原始类实现了至少一个接口,Spring将使用反射和`java.lang.reflect.Proxy`类来创建代理对象。 - **CGLIB代理**:如果原始类没有实现接口,Spring会使用CGLIB库来创建代理,通过继承原始类并覆写其方法来实现。 #### 2. 动态代理的优势 - **减少代码量**:无需为每个原始类编写代理类,只需定义一个或几个通用的额外功能实现。 - **灵活性**:动态代理可以在运行时根据需要生成代理对象,更容易适应需求变化。 - **易于维护**:额外功能的改动只需要在一个地方进行,降低了维护成本。 #### 3. 如何在Spring中配置动态代理 在Spring中,可以通过以下两种方式配置动态代理: - **XML配置**:在`<aop:config>`标签内定义切面,使用`<aop:pointcut>`定义切入点表达式,`<aop:advisor>`定义通知(即额外功能),`<aop:aspect>`定义切面组件。 - **注解配置**:使用`@Aspect`注解定义切面类,`@Pointcut`定义切入点,`@Before`、`@After`、`@Around`等注解定义通知。 ### 实战应用 在实际应用中,Spring AOP常用于以下场景: - **事务管理**:使用`@Transactional`注解,Spring自动在方法调用前后管理事务。 - **日志记录**:通过切面记录方法的执行时间、参数等信息。 - **权限控制**:在方法执行前进行权限校验。 - **性能监控**:计算方法的执行时间,分析系统性能瓶颈。 Spring AOP通过动态代理机制,实现了对核心业务逻辑的解耦,提高了代码的可维护性和扩展性,是Spring框架中不可或缺的一部分。理解并熟练运用AOP,可以极大地提升JavaEE应用的开发效率和质量。
2022-12-13 上传

public class LoginService { @Autowired LoginMapper loginMapper; @Resource private UserMapper userMapper; public Login justLogin(Login login){ return loginMapper.justLogin(login); } public String lkUseridByUsername(String username){ return loginMapper.lkUseridByUsername(username); } public Login selectByUserId(String userId){ return loginMapper.selectByUserId(userId); } public Map<String, Object> getKFUserList(Integer page, Integer limit, Login user) { user.setType(0); user.setPage((page - 1) * limit); user.setLimit(limit); List<Login> userList = loginMapper.getUserList(user); Integer userCount = loginMapper.getUserCount(user); return PageUtils.getTableData(userCount, userList); } public Map<String, Object> getYHUserList(Integer page, Integer limit, Login user) { user.setType(1); user.setPage((page - 1) * limit); user.setLimit(limit); List<Login> userList = loginMapper.getUserList( user); Integer userCount = loginMapper.getUserCount(user); return PageUtils.getTableData(userCount, userList); } public Login getById(String id){ Login byId = loginMapper.getById(id); return byId; } public R addkf(Login login){ Login userName = userMapper.checkUserName(login.getUsername()); if (userName != null){ return R.error().message("用户名已存在"); } Login nickName = userMapper.checkNickName(login.getNickname()); if (nickName != null){ return R.error().message("昵称已存在"); } login.setPassword(Md5Util.StringInMd5(login.getPassword())); UUID uuid = UUID.randomUUID(); login.setUserid(uuid.toString()); login.setType(0); login.setStatus(0); login.setUimg("/img/kefu.jpeg"); userMapper.addLogin(login); userMapper.addUserInfo(login);

2023-06-02 上传