第二章 Spring-AOP
1.1 Spring-AOP概述
- AOP:(全称是Aspect Oriented Programming)面向切面编程。AOP是oop的延续,是函数式编程一种衍生泛型,利用AOP可以对业务逻辑的各个部分进行分离,从而降低各个部分之间的耦合度,提高程序的可重用性,同时提高了开发的效率。
- 简单来说(AOP就是把我们程序中重复的代码抽取出来,在需要执行时,使用动态的代理技术,在不修改源代码的基础上,对我们已有的方法进行增强)。
- AOP的作用和优势:作用,在程序运行期间,在不修改源代码的基础上,对已有的方法进行增强。优势:减少重复代码。提高开发的效率,维护方便。
- AOP的实现方式: 使用动态的代理技术来完成。
- 动态代理有两种方式:一种是基于接口的,一种是基于子类的。
第二章 Spring-AOP的配置【重点】
2.1 Spring中AOP的说明
- Spring中AOP的术语
JoinPoint(连接点): 所谓的连接点就是指那些被拦截的点,在Spring中,这些点指的就是方法,因为Spring只支持基于方法的连接点。 PointCut(切入点):所谓饿切入点就是我们要对那些(JoinPonit)进行拦截定义。 Advice(通知/增强):所谓通知是指拦截到(JoinPoint)之后需要做的事情就是通知。 通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。 Introducation(引介):是一种特殊的通知在不修改类代码的前提下,Introducation可以在运行期间为类动态的的添加一些方法或属性。 Target(目标对象):代理的目标对象。 Weaving(织入):就是把增强应用到目标对象创建新的代理对象的过程。Spring采用动态代理织入,而Aspectj采用编译期织入和类装载织入。 Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。 Aspect(切面):就是切入点和通知(引介)的结合。 在Spring中,框架会会根据目标类是否实现了接口来采用哪种动态代理的方式。 |
2.2基于Xml的AOPde 配置
- Jar包的说明
<!—AOP依赖的织入Jar包--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> <scope>runtime</scope> </dependency> |
- 在Spring配置文件中导入约束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> |
- 配置Spring的AOP
<!--配置Spring的IOC--> <bean id="IAccountDao" class="com.bdit.dao.impl.IAccountDaoImpl"></bean> <bean id="IAccountService" class="com.bdit.Service.impl.AccountServiceImpl"> <property name="iAccountDao" ref="IAccountDao"></property> </bean> |
- 抽取公共日志代码—切面类
import org.apache.log4j.Logger; public class LoggerUtils { //获取日志记录器对象 private Logger logger=Logger.getLogger(LoggerUtils.class); public void beforAd(){ logger.info("***************前置通知*****************"); } public void afterAd(){ System.out.println("***************后置通知*****************"); } } |
- 配置通知类
<!--配置通知类--> <bean id="loggerAd" class="com.bdit.Utils.LoggerUtils"></bean> |
- 配置AOP
<!--配置AOP--> <aop:config> <!--配置切面--> <aop:aspect id="logAspect" ref="loggerAd"> <!--配置切入点--> <aop:pointcut id="mypoint" expression="execution(* com.bdit.Service.impl.*.*(..))"/> <!--配置通知类型--> <!--用于配置前置通知--> <aop:before method="beforAd" pointcut-ref="mypoint"></aop:before> <!--用于配置后置通知--> <aop:after-returning method="afterAd" pointcut-ref="mypoint"></aop:after-returning> <!--用于配置异常通知--> <aop:after-throwing method="afterexception" pointcut-ref="mypoint"></aop:after-throwing> <!--用于配置最终通知类--> <aop:after method="after" pointcut-ref="mypoint"></aop:after> </aop:aspect> </aop:config> </beans> |
- 环绕通知
必须添加一个依赖包 <!--aop会用到织入包aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.5</version> </dependency> |
- Spring配置文件
<!--环绕通知--> <aop:around method="aroundMethod" pointcut-ref="mypoint"></aop:around> |
- 抽取公共日志切面类
public void aroundMethod(ProceedingJoinPoint point){ //获取方法执行所需要的参数,返回的是Object的数组 Object[]args=point.getArgs(); Account account=(Account)args[0]; System.out.println("==========>"+account); try { logger.info("***************开启事物*****************"); point.proceed(args);//执行的目标方法 logger.info("***************提交事物*****************"); } catch (Throwable throwable) { logger.info("***************回滚事物*****************"); throwable.printStackTrace(); }finally { logger.info("***************释放资源*****************"); } } |
- 测试类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations ={"classpath:Spring.xml"}) public class SpringSpp { @Autowired private IAccountService iAccountService;
public void apples(){ Account account= new Account(); account.setZid(1); account.setMoney(23232.232); account.setUid(3); iAccountService.save(account); } } |
2.3 基于注解的AOP[工程搭建]
- 把配置文件的配置替换成注解
<!--基于注解的使用,需要导入一个 context 名称空间的约束--> <!--开启Spring对注解的支持--> <!--指定要扫描的包--> <context:component-scan base-package="com.bdit"/> |
- 使用注解配置通知类
@Component //指定这个类交给Spring管理 public class LoggerUtils { |
- 在通知类上添加一个@Aspect 此注解的作用就是申明当前类为切面类
@Component //指定这个类交给Spring管理 @Aspect //此注解的作用就是申明当前类为切面类 public class LoggerUtils { |
- 配置通知,使用注解配置通知
import com.bdit.entify.Account; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component;
@Component //指定这个类交给Spring管理 @Aspect //此注解的作用就是申明当前类为切面类 public class LoggerUtils { //获取日志记录器对象 private Logger logger=Logger.getLogger(LoggerUtils.class); @Before(value = "execution(* com.bdit.Service.impl.*.*(..))") public void beforAd(){ logger.info("***************前置通知*****************"); } @AfterReturning(value ="execution(* com.bdit.Service.impl.*.*(..))") public void afterAd(){ logger.info("***************后置通知*****************"); } @AfterThrowing(value ="execution(* com.bdit.Service.impl.*.*(..))") public void afterexception(){ logger.info("***************异常通知*****************"); } @After(value ="execution(* com.bdit.Service.impl.*.*(..))") public void after(){ logger.info("***************最终通知*****************"); } |
- 启用Spring对AOP注解的支持
<!--开启Spring对注解的支持--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> |
- 测试类
package com.bdit; import com.bdit.Service.IAccountService; import com.bdit.entify.Account; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//基于纯注解的测试 @RunWith(SpringJUnit4ClassRunner.class) //指定Spring配置文件的位置 @ContextConfiguration(locations ={"classpath:Spring.xml"}) public class SpringSpp { @Autowired //注入数据 private IAccountService iAccountService; @Test public void apples(){ Account account= new Account(); account.setZid(1); account.setMoney(23232.232); account.setUid(3); iAccountService.save(account); } } |
来源:oschina
链接:https://my.oschina.net/u/4244602/blog/3193366