首页 > 其他分享 >基于注解方式声明切面(AOP)

基于注解方式声明切面(AOP)

时间:2023-04-27 22:04:17浏览次数:23  
标签:void System anyMethod 切面 AOP println 注解 public out


基础知识:


首先启动对@AspectJ注解的支持(蓝色部分):

<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" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> 

 <aop:aspectj-autoproxy/> 

 <bean id="orderservice" class="cn.itcast.service.OrderServiceBean"/> 

 <bean id="log" class="cn.itcast.service.LogPrint"/> 

</beans> 


@Aspect 

public class LogPrint { 

 @Pointcut("execution(* cn.itcast.service..*.*(..))") 

 private void anyMethod() {}//声明一个切入点 

 @Before("anyMethod() && args(userName)")//定义前置通知 

 public void doAccessCheck(String userName) { 

 } 

 @AfterReturning(pointcut="anyMethod()",returning="revalue")//定义后置通知 

 public void doReturnCheck(String revalue) { 

 } 

 @AfterThrowing(pointcut="anyMethod()", throwing="ex")//定义例外通知 

 public void doExceptionAction(Exception ex) { 

 } 

 @After("anyMethod()")//定义最终通知 

 public void doReleaseAction() { 

 } 

 @Around("anyMethod()")//环绕通知 

 public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 

 return pjp.proceed(); 

 } 

} 


】 


照样实现步骤如下: 


第一步:导入需要的*.jar 


【 


dist\spring.jar 

lib\jakarta-commons\commons-logging.jar 

如果使用了切面编程(AOP),还需要下列jar文件 

lib/aspectj/aspectjweaver.jar和aspectjrt.jar 

lib/cglib/cglib-nodep-2.1_3.jar 


】 


第二步:根据上面的基础知识导入命名空间: 

 xmlns:aop="http://www.springframework.org/schema/aop" 

 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" 

//打开spring aop 

 <aop:aspectj-autoproxy/> 



第三步:编写我们交个spring管理的拦截器类 


@Aspect//声明切面 

public class MyItercepter { 


 //下面是AOP表达式 

 @Pointcut("execution (* com.liyong.serviceBean.Imp.PersonServiceBean.*(..))") 


 private void anyMethod() {}//声明一个切入点这是切入点名称 


 //下面的前置通知表达式意思是满足anyMethod()切入点并且调用函数参数类型是String 

 @Before("anyMethod() && args(name)") 

 public void doAccessCheck(String name) { 

 //在执行拦截方法前调用可得到输入参数 

 System.out.println("name : "+name); 

 System.out.println("exctution 前置通知"); 

 } 

 //得到返回的结果 returning 是调用方法返回的结果作为doReturnCheck()函数的输入参数 

 @AfterReturning(pointcut="anyMethod()",returning="result") 

 public void doReturnCheck(String result) { 

 //在执行拦截方法后调用可得到返回参数 

 System.out.println("exctution 后置通知"); 

 System.out.println("result : "+result); 

 } 


 @AfterThrowing(pointcut="anyMethod()",throwing="e") 

 public void doExceptionAction(Exception e) { 

 System.out.println("e : "+e); 

 System.out.println("exctution 异常通知"); 

 } 


 @After("anyMethod()") 

 public void doReleaseAction() { 

 System.out.println("exctution 最终通知"); 

 } 


 @Around("anyMethod()") 

 public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 

 System.out.println("exctution 开始环绕测试"); 

 //必须调用下面的方法 

 Object object=pjp.proceed(); 

 System.out.println("exctution 结束环绕测试"); 

 return object; 

 } 



} 


第四步 :编写业务类和接口 


IPersonServiceBean。java PersonServiceBean。java 


public interface IPersonServiceBean { 


 public abstract void save(String name); 


 public abstract String update(String name); 


} 


public class PersonServiceBean implements IPersonServiceBean { 


 public void save(String name) 

 { 

// throw new IllegalArgumentException("抛出异常"); 

 System.out.println("save is invoke"); 

 } 


 public String update(String name) 

 { 


 System.out.println("update is invoke"); 

 return "Sueccess"; 

 } 

} 


第五步:在这里我们使用xml文件的形式来办bean交个spring管理(还有可以通过类路径扫描让spring管理bean见上面的博客) 



<?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" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 

 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 

 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> 

 <aop:aspectj-autoproxy/> 


//下面是我们交个spring管理的 bean 

 <bean id="personService" class="com.liyong.serviceBean.Imp.PersonServiceBean"/> 

 <bean id="myItercepter" class="com.liyong.Itecepter.MyItercepter"/> 


</beans> 


第六步:编写单元测试 


@Test 

public void TestAOP() 

{ 

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); 

IPersonServiceBean personServiceBean =(IPersonServiceBean)context.getBean("personService"); 

//personServiceBean.save("liyong"); 

 personServiceBean.update("xxx"); 

} 


总结: 


这里面最重要和核心的就是怎样编写我们的拦截器类代码然后交个spring管理就OK啦 

知识讲解: 

【 

AOP表达式: 


对某个包及类作拦截: 


 @Pointcut("execution (* com.liyong.serviceBean.Imp.PersonServiceBean.*(..))") 

private void anyMethod() {}//声明一个切入点这是切入点名称 


在上面的切入点execution()方法中第一个*表示这个切入点函数返回的类型为任意类型 

com.liyong.serviceBean.Imp表示包.PersonServiceBean表示这个包下的类 

其中我们也可以这么写com.liyong.serviceBean.Imp.*表示这个包及其子包 

.*(..)表示这个类中的所有方法..表示参数任意类型和个数 


】 


【 

 @Before("anyMethod() && args(name)") 

public void doAccessCheck(String name) { 

 //在执行拦截方法前调用可得到输入参数 

 System.out.println("name : "+name); 

 System.out.println("exctution 前置通知"); 

 } 

@Before表示前置通知 anyMethod()表示这个切入点的名称类似函数 


&& args(name)表示不仅满足anyMethod()这个切入点还满足这个函数参数类型是String 


】 


【 


//得到返回的结果 returning 是调用方法返回的结果作为doReturnCheck()函数的输入参数 

 @AfterReturning(pointcut="anyMethod()",returning="result") 

 public void doReturnCheck(String result) { 

 //在执行拦截方法后调用可得到返回参数 

 System.out.println("exctution 后置通知"); 

 System.out.println("result : "+result); 

 } 


】 


【 


例外通知: 

第一个指明切入点是:anyMethod() 

第二个参数:throwing="e" 表示这个函数抛出一个异常 作为doExceptionAction(..) 

函数的输入值 

@AfterThrowing(pointcut="anyMethod()",throwing="e") 

 public void doExceptionAction(Exception e) { 

 System.out.println("e : "+e); 

 System.out.println("exctution 异常通知"); 

 } 



】 


【 

最终通知: 


anyMethod():切入点名称 

@After("anyMethod()") 

 public void doReleaseAction() { 

 System.out.println("exctution 最终通知"); 

 } 

】 


【 

环绕通知: 


@Around("anyMethod()") 

 public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 

 System.out.println("exctution 开始环绕测试"); 

 //必须调用下面的方法 

 Object object=pjp.proceed(); 

 System.out.println("exctution 结束环绕测试"); 

 return object; 

 } 


】



总结各个通知执行顺序:

第一种:没有环绕通知

当某个方法被拦截到了先执行->前置通知->执行这个拦截函数->(如果出现例外就执行
例外通知)->最终通知

第二种:
<1、有环绕通知没有异常情况下
当某个方法被拦截到了先执行->前置通知->执行到环绕通知里的方法
Object object=pjp.proceed();前面的代码
调用这个函数pjp.proceed();
然后去执行这个拦截的方法
然后执行后置通知
最终通知
然后执行Object object=pjp.proceed();后面的代码

<2、有环绕通知有异常情况下

当某个方法被拦截到了先执行->前置通知->执行到环绕通知里的方法
Object object=pjp.proceed();前面的代码
调用这个函数pjp.proceed();
然后去执行这个拦截的方法
有异常执行这个异常通知
然后执行最终通知
注意:
Object object=pjp.proceed();后面的代码不会被执行

代码见附件。。。。。。。。。。。。。。。。。。。。

标签:void,System,anyMethod,切面,AOP,println,注解,public,out
From: https://blog.51cto.com/u_16091571/6232142

相关文章

  • 基于基于XML配置方式声明切面
    知识点:【//普通的java类publicclassLogPrint{publicvoiddoAccessCheck(){}定义前置通知publicvoiddoReturnCheck(){}定义后置通知publicvoiddoExceptionAction(){}定义例外通知publicvoiddoReleaseAction(){}定义最......
  • AOP中的概念
    基础知识【Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象.joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法......
  • 使用Spring进行面向切面(AOP)编程
    基础知识:【要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间:<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework......
  • @JsonFormat和@DataFormat注解解决前后端日期格式一致性问题
    场景分析场景1:当我们从数据库中查询某篇博客文章数据时,blog表中文章发布日期blog_date这个字段,如果未经过处理,后端查询到的数据传到前端进行展示时,会得到一个不太符合我们要求的日期格式,比如:"blog_date":"2020-12-01T14:25:31.296+0000",为了解决这个问题,将后端返回给前端的日......
  • Spring AOP 支持两种模式的动态代理
    SpringAOP支持两种模式的动态代理,JDKProxy或者cglib,jdkproxy:publicclassMyDynamicProxy{publicstaticvoidmain(String[]args){HelloImplhello=newHelloImpl();MyInvocationHandlerhandler=newMyInvocationHandler(hello);......
  • spring aop 注解方式
    前置、后置、环绕、切面、切点packagecom.springinaction.springidol;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.AfterReturning;importorg.aspectj.lang.annotation.AfterThrowing;importorg.aspectj.lang.annotation.Around;imp......
  • spring aop xml方式
    工程如图:pom文件内容:<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd" xmlns......
  • 第10章 枚举类和注解
    1.枚举类的使用枚举类的实现:在JDK1.5之前需要自定义枚举类在JDK1.5之后新增了enum关键字用于定义枚举类枚举类的属性:枚举类对象的属性不应允许被改动,所以应该使用privatefinal进行修饰。(若枚举只有一个对象,则可以作为一种单例模式的实现方式,即privatefinal类名instance=......
  • Python面向切面编程-语法层面和functools模块
    1,Python语法层面对面向切面编程的支持(方法名装饰后改变为log)__author__='Administrator'importtimedeflog(func):defwrapper(*args):start=time.time()func(args)end=time.time()print'funcusedtimeis:',end-st......
  • Springboot日期注解失败:while it seems to fit format ‘yyyy-MM-dd‘T‘HH:mm:ss.SSS
    提交字符串到后台映射为Date类型可以加上@DateTimeFormat(pattern="yyyy-MM-ddHH:mm:ss")注解,但是报错了!前端提交字符串到后台,出现如下错误:whileitseemstofitformat'yyyy-MM-dd'T'HH:mm:ss.SSSZ',parsingfails(leniency?null))错误的大致意思就是字符串映射到Da......