选择切点

  Spring是方法级别的AOP框架,而我们主要也是以某个类的某个方法作为切点,用动态代理的理论来说,就是要拦截哪个方法织入对应AOP通知。
  代码清单:打印角色接口

  1. package com.ssm.chapter11.aop.service;
  2.  
  3. import com.ssm.chapter11.game.pojo.Role;
  4.  
  5. public interface RoleService {
  6.  
  7. // public void printRole(Role role);
  8.  
  9. public void printRole(Role role, int sort);
  10.  
  11. }

  代码清单:RoleService实现类

  1. package com.ssm.chapter11.aop.service.impl;
  2.  
  3. import org.springframework.stereotype.Component;
  4. import com.ssm.chapter11.aop.service.RoleService;
  5. import com.ssm.chapter11.game.pojo.Role;
  6.  
  7. @Component
  8. public class RoleServiceImpl implements RoleService {
  9.  
  10. // @Override
  11. // public void printRole(Role role) {
  12. // System.out.println("{id: " + role.getId() + ", " + "role_name : " + role.getRoleName() + ", " + "note : " + role.getNote() + "}");
  13. // }
  14.  
  15. public void printRole(Role role, int sort) {
  16. System.out.println("{id: " + role.getId() + ", " + "role_name : " + role.getRoleName() + ", " + "note : " + role.getNote() + "}");
  17. System.out.println(sort);
  18. }
  19.  
  20. }

  这个类没什么特别的,只是这个时候如果把printRole作为AOP的切点,那么用动态代理的语言就是要为类RoleServi-ceImpl生成代理对象,然后拦截printRole方法,于是可以产生各种AOP通知方法。

创建切面

  选择好了切点就可以创建切面了,对于动态代理的概念而言,它就如同一个拦截器,在Spring中只要使用@Aspect注解一个类,那么Spring IoC容器就会认为这是一个切面了

  1. package com.ssm.chapter11.aop.aspect;
  2.  
  3. import com.ssm.chapter11.aop.verifier.RoleVerifier;
  4. import com.ssm.chapter11.aop.verifier.impl.RoleVerifierImpl;
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.annotation.*;
  7.  
  8. @Aspect
  9. public class RoleAspect {
  10.  
  11. @DeclareParents(value = "com.ssm.chapter11.aop.service.impl.RoleServiceImpl+", defaultImpl = RoleVerifierImpl.class)
  12. public RoleVerifier roleVerifier;
  13.  
  14. @Pointcut("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
  15. public void print() {
  16. }
  17.  
  18. // @Before("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
  19. // @Before("execution(* com.ssm.chapter11.*.*.*.*.printRole(..)) && within(com.ssm.chapter11.aop.service.impl.*)")
  20. @Before("print()")
  21. // @Before("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..)) && args(role, sort)")
  22. public void before() {
  23. System.out.println("before ....");
  24. }
  25.  
  26. @After("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
  27. public void after() {
  28. System.out.println("after ....");
  29. }
  30.  
  31. @AfterReturning("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
  32. public void afterReturning() {
  33. System.out.println("afterReturning ....");
  34. }
  35.  
  36. @AfterThrowing("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
  37. public void afterThrowing() {
  38. System.out.println("afterThrowing ....");
  39. }
  40.  
  41. @Around("print()")
  42. public void around(ProceedingJoinPoint jp) {
  43. System.out.println("around before ....");
  44. try {
  45. jp.proceed();
  46. } catch (Throwable e) {
  47. e.printStackTrace();
  48. }
  49. System.out.println("around after ....");
  50. }
  51.  
  52. }

连接点

  Spring是如何判断是否需要拦截方法的,毕竟并不是所有的方法都需要使用AOP编程,这就是一个连接点的问题。在注解中定义了execution的正则表达式,Spring是通过这个正则表达式判断是否需要拦截你的方法的,这个表达式是:
  execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))
  依次对这个表达式做出分析。
  •execution:代表执行方法的时候会触发。
  •*:代表任意返回类型的方法。
  •com.ssm.chapter11.aop.service.impl.RoleServiceImpl:代表类的全限定名。
  •printRole:被拦截方法名称。
  •(..):任意的参数。
  显然通过上面的描述,全限定名为com.ssm.chapter11.aop.service.impl.RoleServiceImpl的类的printRole方法被拦截了,这样它就按照AOP通知的规则把方法织入流程中。

测试AOP

  代码清单:配置Spring bean

  1. package com.ssm.chapter11.aop.config;
  2.  
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.ComponentScan;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  7. import com.ssm.chapter11.aop.aspect.RoleAspect;
  8.  
  9. @Configuration
  10. @EnableAspectJAutoProxy
  11. @ComponentScan("com.ssm.chapter11.aop")
  12. public class AopConfig {
  13.  
  14. @Bean
  15. public RoleAspect getRoleAspect() {
  16. return new RoleAspect();
  17. }
  18.  
  19. }

  Spring还提供了XML的方式,这里就需要使用AOP的命名空间了

  1. <?xml version='1.0' encoding='UTF-8' ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  5. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  6. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
  7.  
  8. <aop:aspectj-autoproxy/>
  9. <bean id="roleAspect" class="com.ssm.chapter11.aop.aspect.RoleAspect"/>
  10. <bean id="roleService" class="com.ssm.chapter11.aop.service.impl.RoleServiceImpl"/>
  11.  
  12. </beans>

  无论用XML还是用Java的配置,都能使Spring产生动态代理对象,从而组织切面,把各类通知织入到流程当中

  代码清单:测试AOP流程

  1. package com.ssm.chapter11.aop.main;
  2.  
  3. import com.ssm.chapter11.aop.verifier.RoleVerifier;
  4. import com.ssm.chapter11.aop.verifier.impl.RoleVerifierImpl;
  5. import org.aspectj.lang.annotation.DeclareParents;
  6. import org.springframework.context.ApplicationContext;
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;
  8. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  9. import com.ssm.chapter11.aop.config.AopConfig;
  10. import com.ssm.chapter11.aop.service.RoleService;
  11. import com.ssm.chapter11.game.pojo.Role;
  12.  
  13. public class Main {
  14.  
  15. public static void main(String[] args) {
  16.  
  17. ApplicationContext ctx = new AnnotationConfigApplicationContext(AopConfig.class);
  18. // 使用XML使用ClassPathXmlApplicationContext作为IoC容器
  19. // ApplicationContext ctx = new ClassPathXmlApplicationContext("ssm/chapter11/spring-cfg3.xml");
  20. RoleService roleService = ctx.getBean(RoleService.class);
  21.  
  22. Role role = new Role();
  23. role.setId(1L);
  24. role.setRoleName("role_name_1");
  25. role.setNote("note_1");
  26.  
  27. RoleVerifier roleVerifier = (RoleVerifier) roleService;
  28. if (roleVerifier.verify(role)) {
  29. roleService.printRole(role, 1);
  30. }
  31. System.out.println("####################");
  32. //测试异常通知
  33. // role = null;
  34. // roleService.printRole(role);
  35. }
  36.  
  37. }

spring 使用@AspectJ注解开发Spring AOP的更多相关文章

  1. Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探

    由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...

  2. 使用@AspectJ注解开发Spring AOP

    一.实体类: Role public class Role { private int id; private String roleName; private String note; @Overr ...

  3. Spring Aop(二)——基于Aspectj注解的Spring Aop简单实现

    转发地址:https://www.iteye.com/blog/elim-2394762 2 基于Aspectj注解的Spring Aop简单实现 Spring Aop是基于Aop框架Aspectj实 ...

  4. Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AOP编程比较

    本篇博文用一个稍复杂点的案例来对比一下基于XML配置与基于AspectJ注解配置的AOP编程的不同. 相关引入包等Spring  AOP编程准备,请参考小编的其他博文,这里不再赘述. 案例要求: 写一 ...

  5. spring boot纯注解开发模板

    简介 spring boot纯注解开发模板 创建项目 pom.xml导入所需依赖 点击查看源码 <dependencies> <dependency> <groupId& ...

  6. Spring:基于注解的Spring MVC

    什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...

  7. Spring自动装配----注解装配----Spring自带的@Autowired注解

    Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx; public interface Person { public voi ...

  8. Spring使用AspectJ注解和XML配置实现AOP

    本文演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP 下面是使用AspectJ注解实现AOP的Java Project首先是位于classpath下的applicationC ...

  9. Spring注解开发系列Ⅵ --- AOP&事务

    注解开发 --- AOP AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,横向重复,纵向抽取.详细的AO ...

随机推荐

  1. LOJ P10131 暗的连锁 题解

    每日一题 day27 打卡 Analysis 对于每条非树边 , 覆盖 x 到 LCA 和 y到 LCA 的边 , 即差分算出每个点和父亲的连边被覆盖了多少次 .被覆盖 0 次的边可以和 m 条非树边 ...

  2. ES 基础理论 配置调优

    一.简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为 ...

  3. 【MongoDB】在C#中使用

    一.MongoClient类 在2.10.0版本中引入了MongoClient类,同时在其API中也说明了Mongo类会在将来的版本中被MongoClient替换(Note: This class h ...

  4. RookeyFrame 自定义数据源 返回统计查询后的视图

    核心:对返回的数据进行重写 功能是这样的:上传淘宝后台的订单文件,将订单文件里面的数据导入到系统,对导入后的订单数据进行统计后再显示. Order_File:用来存上传的订单文件,格式是****.cs ...

  5. Ubuntu 下面手动安装 Redis

    1.下载 wget http://download.redis.io/releases/redis-2.8.17.tar.gz .tar.gz cd redis- make 2.复制文件到bin目录 ...

  6. AttributeError: module 'tensorflow' has no attribute 'set_random_seed'

    anaconda3 python3.7 安装好tensorflow 后出现上面的问题,原因是安装的tensorflow版本是2.0的,所以使用以前的代码tensorflow中的函数不兼容.

  7. Mujin Programming Challenge 2017题解

    传送门 \(A\) 似乎并不难啊然而还是没想出来-- 首先我们发现对于一个数\(k\),它能第一个走到当且仅当对于每一个\(i<k\)满足\(x_i\geq 2i-1\),这样我们就可以把所有的 ...

  8. 《自制编程语言--基于C语言 郑钢》学习笔记

    <自制编程语言>学习笔记 本仓库内容 <自制编程语言>源码 src/sparrow.tgz <自制编程语言>读书笔记 docs/* <自制编程语言>样章 ...

  9. Linux shell head 命令

    输出前25行 head -n25 input.txt head -n input.txt head - input.txt 输出前5个字符 head -c5 test.cpp head -c test ...

  10. andriod studio命名规范

    标识符命名法标识符命名法最要有四种: 1 驼峰(Camel)命名法:又称小驼峰命名法,除首单词外,其余所有单词的第一个字母大写. 2 帕斯卡(pascal)命名法:又称大驼峰命名法,所有单词的第一个字 ...