public class User { private Integer id; private String username; private String note; public User(Integer id, String username, String note) { this.id = id; this.username = username; this.note = note; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } @Override public String toString() { return "User{" + "id=" + id + ", username=‘" + username + ‘\‘‘ + ", note=‘" + note + ‘\‘‘ + ‘}‘; } }
接口:
//@Component接口不用添加注入到容器,因为接口不能进行实例化 public interface UserService { public void printUser(User user); public void manyAspect(); }
实现类:
@Component public class UserServiceImpl implements UserService { /** * 这个方法将作为我们的AOP的接入点 * @param user */ @Override public void printUser(User user) { if (user.getUsername() == null){ throw new RuntimeException("检查用户参数是否为空。。。。"); } System.out.println("id = "+ user.getId()); System.out.println("username = " + user.getUsername()); System.out.println("note = " + user.getNote()); } @Override public void manyAspect() { System.out.println("manyAspect------"); } }
/** * 定义切面 * @Aspect声明切面 */ //@Aspect public class MyAspect { //避免我们重复写一个表达式,引入了切入点概念PointCut,描述哪些类的哪些方法需要开启AOP编程。 @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))") public void pointCut(){ } @Before("pointCut()") public void before(){ System.out.println("before......"); } @After("pointCut()") public void after(){ System.out.println("after......"); } @AfterReturning("pointCut()") public void afterreturning(){ System.out.println("agterreturning....."); } @AfterThrowing("pointCut()") public void afterthrowing(){ System.out.println("afterthrowing....."); } /** * ProceedingJoinPoint类型参数,给参数的对象中有个方法proceed方法。回调原来的方法。 * @Around注解会取代原有目标的方法的通知。不进行回调得时候,方法是空的。 * @param joinPoint * @throws Throwable */ @Around("pointCut()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("around before...."); //可以在这里打断点去查看joinPoint的内容 joinPoint.proceed(); System.out.println("around after...."); } /** * http://localhost:8080/aop/userprint?id=22&username=quan¬e=huolala * 有回调: * around before... * before...... * id = 22 * username = quan * note = huolala * agterreturning..... * after...... * around after.... * ################ * 没回调: * around before.... * around after.... */ /** * @DeclareParents作用:引入新的类来增强服务, * value:指向你要增强功能的目标对象,这里要增强对象为UserServiceImpl对象 * defaultImpl:引入增强功能的类,UserValidatorImpl提供校验用户是否为空的 */ @DeclareParents(value = "quan.springframework.springbootaop.aopdone.UserServiceImpl",defaultImpl = UserValidatorImpl.class) public UserValidator userValidator; @DeclareParents(value = "quan.springframework.springbootaop.aopdone.UserServiceImpl",defaultImpl = UserValidatorIdImpl.class) public UserValidatorId userValidatorId; /** * 通知获取参数, * && args(user)并将目标对象方法-名称为user的参数传递进来。 * @param joinPoint * @param user * 注意: * JoinPoint类型的参数对于非环绕通知而言的参数。spring AOP自动传递到通知中 * 环绕通知自动你传递的参数为ProceedingJoinPoint类型的参数。 */ @Before("pointCut() && args(user)") public void beforeParam(JoinPoint joinPoint,User user){ Object[] args = joinPoint.getArgs(); System.out.println(args); System.out.println("before param...."); } // @Before("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))") // public void before(){ // System.out.println("before......"); // } // // @After("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))") // public void after(){ // System.out.println("after......"); // } // // @AfterReturning("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))") // public void afterreturning(){ // System.out.println("agterreturning....."); // } // // @AfterThrowing("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..))") // public void afterthrowing(){ // System.out.println("afterthrowing....."); // } /** * execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.printUser(..)) * execution:表示执行时,拦截里面的正则匹配方法; * *:表示任意返回类型的方法 * quan.springframework.springbootaop.aopdone.UserServiceImpl:指定目标对象的全限定类名 * printUser:指定目标对象的方法 * (**):表示任意参数进行匹配 */ }
多切面:
/** * 第一个切面 */ @Order(3) @Aspect public class MyManyAop { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))") public void manyAspects(){ } @Before("manyAspects()") public void before(){ System.out.println("MymanyAop1---before......"); } @After("manyAspects()") public void after(){ System.out.println("MymanyAop1---after......"); } @AfterReturning("manyAspects()") public void afterreturning(){ System.out.println("MymanyAop1---agterreturning....."); } }
/** * 第二个切面 */ @Order(2) @Aspect public class MyManyAop2 { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))") public void manyAspects(){ } @Before("manyAspects()") public void before(){ System.out.println("MymanyAop2---before......"); } @After("manyAspects()") public void after(){ System.out.println("MymanyAop2---after......"); } @AfterReturning("manyAspects()") public void afterreturning(){ System.out.println("MymanyAop2---agterreturning....."); } }
/** * 第三个切面 */ @Order(1) @Aspect public class MyManyAop3 { @Pointcut("execution(* quan.springframework.springbootaop.aopdone.UserServiceImpl.manyAspect(..))") public void manyAspects(){ } @Before("manyAspects()") public void before(){ System.out.println("MymanyAop3---before......"); } @After("manyAspects()") public void after(){ System.out.println("MymanyAop3---after......"); } @AfterReturning("manyAspects()") public void afterreturning(){ System.out.println("MymanyAop3---agterreturning....."); } }
各个切面需要加入到容器当中:
@Configuration public class AopConfiguration { /** * 需要将切面加入到容器当中才能被织入 * @return */ @Bean("myAspect") public MyAspect initMyAspect(){ return new MyAspect(); } /** * 第一个切面 */ @Bean("myManyAop") public MyManyAop initMyManyAspect1(){ return new MyManyAop(); } /** * 第二个切面 */ @Bean("myManyAop2") public MyManyAop2 initMyManyAspect2(){ return new MyManyAop2(); } /** * 第三个切面 */ @Bean("myManyAop3") public MyManyAop3 initMyManyAspect3(){ return new MyManyAop3(); } }
通过类增强的:
/** * 新建一个增强接口 */ public interface UserValidator { public boolean validate(User user); } /** * 增强接口实现类 */ public class UserValidatorImpl implements UserValidator { @Override public boolean validate(User user) { System.out.println("add validate"); return user.getUsername() != null; } }
public interface UserValidatorId { public boolean idBigTWY(User user); } public class UserValidatorIdImpl implements UserValidatorId{ @Override public boolean idBigTWY(User user) { System.out.println("UserValidatorId"); return user.getId() > 20; } }
什么是织入:
/** * 织入:生成动态代理对象并且将切面和目标对象方法编织称为约定流程的过程 * Spring推荐的方式是接口+实现类的模式。 * spring支持JDK和CGLIB; * JDK要求被代理对象必须拥有接口。 * CGLIB不做要求 * spring处理规则:当需要使用AOP的类拥有接口时,会以JDK动态代理运行,否则已CGLIB运行 * 注意: * Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。 * SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB。 */
@Controller @RequestMapping("/aop") public class AopController { @Autowired UserService userService; @RequestMapping("/userprint") @ResponseBody public User pringUser(Integer id,String username,String note){ User user = new User(id,username,note); userService.printUser(user); return user; } /** * request: *http://localhost:8080/aop/userprint?id=22&username=quan¬e=huolala * result: * before...... * id = 22 * username = quan * note = huolala * agterreturning..... * after...... */ @RequestMapping("/quote") @ResponseBody public User validateAndPrint(int id,String username,String note){ User user = new User(id,username,note); //强制转换为UserValidator。 UserValidator userValidator = (UserValidator)userService; if ( userValidator.validate(user) ){//判断是否为空user.username是否为空 userService.printUser(user); } UserValidatorId userValidatorId = (UserValidatorId)userService; if (userValidatorId.idBigTWY(user)){ System.out.println(user.getId()); } return user; } @RequestMapping("/many") @ResponseBody public String many(){ userService.manyAspect(); return "many aspect"; } /** * 顺序不一样的。 * MymanyAop1---before...... * MymanyAop2---before...... * MymanyAop3---before...... * manyAspect------ * MymanyAop3---agterreturning..... * MymanyAop3---after...... * MymanyAop2---agterreturning..... * MymanyAop2---after...... * MymanyAop1---agterreturning..... * MymanyAop1---after...... */ /** * 加入Order: * MymanyAop3---before...... * MymanyAop2---before...... * MymanyAop1---before...... * manyAspect------ * MymanyAop1---agterreturning..... * MymanyAop1---after...... * MymanyAop2---agterreturning..... * MymanyAop2---after...... * MymanyAop3---agterreturning..... * MymanyAop3---after...... * 前置通知before都是从小到大运行,而后置通知和返回通知都是从大到小运行 * 典型的责任链模式顺序。 */ }
原文:https://www.cnblogs.com/java-quan/p/13730971.html