sring aop的方式有两种:(1)xml文件配置方式(2)注解的方式实现,我们可以先通过一个demo认识spring aop的实现,然后再对其进行详细的解释。

一、基于注解的springAop配置。

  环境准备阶段:

  (1)pom.xml:

 <dependencies>
<!-- 引入Spring-AOP等相关Jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency> <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>

 (2)定义接口:

 package cn.spring.aop.dao;

 /**
* @author Simple
* @date 10:01 2019/8/20
* @description
*/
public interface UserService {
public void save();
}

 (3)接口实现类:

 package cn.spring.aop.dao;

 import org.springframework.stereotype.Service;

 /**
* @author Simple
* @date 9:57 2019/8/20
* @description
*/
@Service
public class UserServiceImpl implements UserService { @Override
public void save() {
System.out.println("保存成功.....");
}
}

 (4)Aop类: 

 package cn.spring.aop;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component; /**
* @author Simple
* @date 10:06 2019/8/20
* @description
*/
@Component
@Aspect
public class AopAspect {
/**
* 前置通知
*/
@Before("execution(* cn.spring.aop.dao.UserService.save(..))")
public void before(){
System.out.println("前置通知....");
} /**
* 后置通知
* returnVal,切点方法执行后的返回值
*/
@AfterReturning(value="execution(* cn.spring.aop.dao.UserService.save(..))",returning = "returnVal")
public void AfterReturning(Object returnVal){
System.out.println("后置通知...."+returnVal);
} /**
* 环绕通知
* @param joinPoint 可用于执行切点的类
* @return
* @throws Throwable
*/
@Around("execution(* cn.spring.aop.dao.UserService.save(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知前....");
Object obj= (Object) joinPoint.proceed();
System.out.println("环绕通知后....");
return obj;
} /**
* 抛出通知
* @param e
*/
@AfterThrowing(value="execution(* cn.spring.aop.dao.UserService.save(..))",throwing = "e")
public void afterThrowable(Throwable e){
System.out.println("出现异常:msg="+e.getMessage());
} /**
* 无论什么情况下都会执行的方法
*/
@After(value="execution(* cn.spring.aop.dao.UserService.save(..))")
public void after(){
System.out.println("最终通知....");
}
}

 (5)spring.xml

 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.spring.aop"></context:component-scan>
<!-- 启动@aspectj的自动代理支持-->
<aop:aspectj-autoproxy />
</beans>

 (6)测试类:

 package cn.spring.aop;

 import cn.spring.aop.dao.UserService;
import cn.spring.aop.dao.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author Simple
* @date 10:13 2019/8/20
* @description
*/
public class TestDemo {
public static void main(String[] args) {
ApplicationContext ac =new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) ac.getBean("userServiceImpl");
userService.save();
}
}

 (7)运行结果:

二、配置详解

(1)spring.xml中注解的作用

1.spring--<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

   这个是 开启事物注解权限,引入了三个jar包  aspectjweaver.jar aspectjrt.jar aspectj.jar  aopalliance.jar。

  2.Spring -- <context:component-scan>

   在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean。

(2)Aop类中的注解

在aop类中,编写了5种注解类型的通知函数:

   @Before 前置通知

   @AfterReturning 后置通知

   @Around 环绕通知

   @AfterThrowing 异常通知

   @After 最终通知

   @pointcut 定义切点匹配表达式

(3)切点表达式

  1. execution

   由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且在Spring中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如下是execution表达式的语法:

 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

 这里问号表示当前项可以有也可以没有,其中各项的语义如下:
  • modifiers-pattern方法的可见性,如public,protected;
  • ret-type-pattern:方法的返回值类型,如int,void等;
  • declaring-type-pattern:方法所在类的全路径名,如com.spring.Aspect;
  • name-pattern:方法名类型,如buisinessService();
  • param-pattern:方法的参数类型,如java.lang.String;
  • throws-pattern:方法抛出的异常类型,如java.lang.Exception;

如下是一个使用execution表达式的例子:

  execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))

上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。

   通配符的类型,主要有两种:

  • *通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词。

如下示例表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法:execution(* com.spring.service.BusinessObject.*())

  • ..通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中,如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。

如下示例表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数:execution(* com.spring.service..*.businessService())

这里需要说明的是,包路径service..*.businessService()中的..应该理解为延续前面的service路径,表示到service路径为止,或者继续延续service路径,从而包括其子包路径;后面的*.businessService(),这里的*表示匹配一个单词,因为是在方法名前,因而表示匹配任意的类。

如下示例是使用..表示任意个数的参数的示例,需要注意,表示参数的时候可以在括号中事先指定某些类型的参数,而其余的参数则由..进行匹配:

execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))

三、基于xml的SpringAop配置

  xml配置主要是将注解转换为xml这里我们在上述的情况下做下修改,主要修改两个地方:1,spring.xml,2 aop类

1.springaop.xml

 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--基于配置需要我们手动进行配置-->
<!-- dao 实例 -->
<bean id="userService" class="cn.spring.aop.dao.UserServiceImpl"></bean>
<!-- 切面类 -->
<bean id="aop" class="cn.spring.aop.AopAspect2"></bean>
<!-- Aop配置 -->
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* cn.spring.aop.dao.UserService.*(..))" id="pt"/>
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt"/>
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="before" pointcut-ref="pt"/>
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt"/>
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning" pointcut-ref="pt" />
<!-- 异常通知 -->
<aop:after-throwing method="after" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>

 2.aop类  AopAspect2

 package cn.spring.aop;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component; /**
* @author Simple
* @date 10:06 2019/8/20
* @description
*/
@Component
@Aspect
public class AopAspect2 {
/**
* 前置通知
*/
public void before(){
System.out.println("前置通知....");
} /**
* 后置通知
* returnVal,切点方法执行后的返回值
*/
public void afterReturning(){
System.out.println("后置通知....");
} /**
* 环绕通知
* @param joinPoint 可用于执行切点的类
* @return
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知前....");
Object obj= (Object) joinPoint.proceed();
System.out.println("环绕通知后....");
return obj;
} /**
* 抛出通知
* @param e
*/
public void afterThrowable(Throwable e){
System.out.println("出现异常:msg="+e.getMessage());
} /**
* 无论什么情况下都会执行的方法
*/
public void after(){
System.out.println("最终通知....");
}
}

 3.测试方法

 package cn.spring.aop;

 import cn.spring.aop.dao.UserService;
import cn.spring.aop.dao.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author Simple
* @date 10:13 2019/8/20
* @description
*/
public class TestDemo {
public static void main(String[] args) {
ApplicationContext ac =new ClassPathXmlApplicationContext("springaop.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.save();
}
}

 4.运行结果

现在在开发中主要是使用注解进行开发,方便快捷,但是更多的是配置和注解一块使用,springaop在配置方面很多都是这种注解加配置,原因主要是方便管理维护。我们这里主要讲的是两种方式的使用和切点表达式。

最新文章

  1. Hash_bzoj1862: [Zjoi2006]GameZ游戏排名系统
  2. Sublime Text 3 破解版 + 注册机 + 汉化包 + 教程
  3. C++基础内容复习
  4. Unity-Animator深入系列---目标匹配Target Matching
  5. Fedora20 编译安装qemu-system
  6. dotnetfx35.exe
  7. 玩转Web之easyui(三)-----easy ui dataGird 重新指定url以获取不同数据源信息
  8. 多线程编程 (2) -NSOperation
  9. Android NDK进入发展
  10. iscroll的下拉刷新,上拉翻页。
  11. visual studio 目录
  12. SyntaxError: Unexpected token &lt; in JSON at position 0 错误
  13. selenium的使用技巧及集成到scrapy
  14. JAVA面向对象-----成员内部类访问细节
  15. fstat函数
  16. Python开发——数据类型【集合】
  17. pyspider爬一批文章保存到word中
  18. 错误:在非结构或联合中请求成员‘next’
  19. 2019.02.09 bzoj1042: [HAOI2008]硬币购物(完全背包+容斥原理)
  20. php-fpm 记录慢执行日志

热门文章

  1. Java NIO学习系列六:Java中的IO模型
  2. Spring框架使用@Autowired自动装配引发的讨论
  3. SPFA队列优化
  4. Chrome 跨域 disable-web-security 关闭安全策略
  5. SQL注入详解及技巧
  6. Unity经典游戏编程之:球球大作战
  7. python_Tensorflow学习(三):TensorFlow学习基础
  8. 七天学会NodeJS——第一天
  9. java8(1)--- lambda
  10. Android 使用 DiffUtil 处理 RecyclerView 数据更新问题