定义
什么叫Spring面向切面编程(AOP),请自行百度,这边就不做详细介绍了。
场景
有两个对象,字典和工程信息Bean,每次新增或修改对象时,记录新增和修改的时间。
基类定义
package myTest.entity; import lombok.Data; import java.time.LocalTime; /** * entity基类 */ @Data public class BaseEntity { private Long id; private LocalTime createTime; private LocalTime updateTime; }
子类定义
package myTest.entity; import lombok.Data; /** * 字典信息 */ @Data public class DictEntity extends BaseEntity{ private String key; private String value; }
package myTest.entity; import lombok.Data; /** * 项目信息 */ @Data public class ProjectEntity extends BaseEntity { private String projectName; }
注:这边使用了lombok,不熟悉的同学可以查看https://www.cnblogs.com/meituan/p/10510889.html
常规做法
service基类
package myTest.service; public interface BaseService<T> { void save(T entity); void update(T entity); }
字典Service实现
package myTest.service; import myTest.entity.DictEntity;import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalTime; public class DictService implements BaseService<DictEntity> { @Autowired private DictDao dao; @Override public void save(DictEntity entity){ entity.setCreateTime(LocalTime.now()); entity.setUpdateTime(LocalTime.now()); dao.save(entity); } @Override public void update(DictEntity entity){ entity.setUpdateTime(LocalTime.now()); dao.update(entity); } }
工程Service实现
package myTest.service; import myTest.entity.ProjectEntity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalTime; @Service public class ProjectService implements BaseService<ProjectEntity> { @Autowired private ProjectDao dao; @Override public void save(ProjectEntity entity){ entity.setCreateTime(LocalTime.now()); entity.setUpdateTime(LocalTime.now()); dao.save(entity); } @Override public void update(ProjectEntity entity){ entity.setUpdateTime(LocalTime.now()); dao.update(entity); } }
反思
常规做法做了重复劳动工作,如果entity子类更多的话,重复劳动会更多,而且很不容易维护,这时候就可以用到Spring的切面编程思想。
使用Spring AOP解决问题
大致思路可以这样,当Service执行save和update方法的时候,定义一个切点,在执行到这个切点的时候,统一加入更新时间和新增时间的控制,一处增加,多处使用,省时省力,而且便于维护。上代码!
- 首先,在pom文件中引入aspect依赖的jar包,如下
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency>
- 其次,定义切点和前置通知
package myTest; import myTest.entity.BaseEntity; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import java.time.LocalTime; import java.util.Arrays; import java.util.List; /** * 定义切点和前置通知,统一修改新增时间和修改时间 */ @Aspect @Component public class Asepect { @Pointcut("execution(* myTest.service.DictService.save*(..)) || execution(* myTest.service.DictService.update*(..)) || " + "execution(* myTest.service.ProjectService.save*(..)) || execution(* myTest.service.ProjectService.update*(..))") public void addAndUpdatePointCut(){} @Before("addAndUpdatePointCut()") public void before(JoinPoint joinPoint) { //获取方法名 String mathName = joinPoint.getSignature().getName(); //获取参数列表 List<Object> args = Arrays.asList(joinPoint.getArgs()); for (Object o : args) { if (o instanceof BaseEntity) { ((BaseEntity) o).setUpdateTime(LocalTime.now()); if (mathName.startsWith("save")) { ((BaseEntity) o).setCreateTime(LocalTime.now()); } } } } }
就这样两个简单的步骤,就可以解决原始方法带来的重复工作和不易维护的问题,是不是很爽?
【纯手打,请多多支持,谢谢】