`
zhaohaolin
  • 浏览: 982091 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring Aop实现——Annotation方式(注解式)

    博客分类:
  • JAVA
 
阅读更多

Spring Aop实现——Annotation方式(注解式)

一、spring依赖库
* SPRING_HOME/dist/spring.jar
* SPRING_HOME/lib/jakarta-commons/commons-logging.jar
* SPRING_HOME/lib/log4j/log4j-1.2.14.jar
* SPRING_HOME/lib/aspect j/*.jar

二、编写切面aspect类

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;


/**
* 定义切面
* @author
*
*/
@Aspect
public class CheckAspect {


/**
* 定义切入点(Pointcut),Pointcut的名称就是allSaveMethod, 此方法不能有参数和返回值,仅是个标识。
* Pointcut的内容——"execution(*, save*(..))", 是个表达式, 描述哪些对象的哪些方法(订阅Joinpoint)
*
*/
@Pointcut("execution(* save*(..)) || execution(* del*(..))")
private void allSaveMethod(){};



/*
* 定义通知advice(before型), 标识在哪个切入点(allSaveMethod),织入(weaver)此方法
*/
@Before("allSaveMethod()")
public void checkUser(){
   System.out.println("=======CheckAspect.checkUser()===========");
}

}

 

测试服务类:

public class UserManagerImpl implements IUserManager {

public void delUser(int id) {
   System.out.println("=====UserManagerImpl.delUser()===========");
}

public String findUser(int id) {
   System.out.println("=====UserManagerImpl.findUser()===========");
   return null;
}

public void saveUser(String username, String password) {
         System.out.println("=====UserManagerImpl.saveUser()===========");
}

public void updateUser(int id) {
   System.out.println("=====UserManagerImpl.updateUser()===========");
}

 

}

 

三、applicationContext.xml中开启aop,配置相关切面aspect类

<?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:aop="http://www.springframework.org/schema/aop "
xmlns:tx="http://www.springframework.org/schema/tx "
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd "
           >

<!-- 启用aop -->
<aop:aspectj-autoproxy/>

<!--配置aspect-->
<bean id="checkAspect" class="com.CheckAspect" />


<bean id="userManager" class="com.manager.impl.UserManagerImpl" />

 

</beans>

 

四、测试用例:

public void testAspect(){
   BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
  IUserManager userManager = (IUserManager) factory.getBean("userManager");//生成的代理类proxy
   userManager.saveUser("cat", "123");
   userManager.delUser(1);

userManager.updateUser(1); //没有调用切面advice,因为方法update与之不匹配。
}

执行结果:

=======CheckAspect.checkUser()===========
=====UserManagerImpl.saveUser()===========
=======CheckAspect.checkUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========

 

=======================================

Schema-based式(xml配置)

一、类:

/**
* 定义切面
* @author dell
*
*/
public class CheckAspect {

/*
* 定义通知advice(before型),标识在哪个切入点(allSaveMethod),织入(weaver)此方法
*/
public void checkUser(){
   System.out.println("=======CheckAspect.checkUser()===========");
}

}

 

二、applicationcontex.xml配置

<?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:aop="http://www.springframework.org/schema/aop "
xmlns:tx="http://www.springframework.org/schema/tx "
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd "
           >


<bean id="checkAspect" class="com.CheckAspect" />
<bean id="userManager" class="com.manager.impl.UserManagerImpl" />

<aop:config>
   <!-- 配置切面appect , ref切面类 -->
   <aop:aspect id="check" ref="checkAspect">
       <!-- 配置切入点pointcut, 定义一个表达式 -->
       <aop:pointcut id="allSaveMethod" expression="execution(* com.manager.impl.UserManagerImpl.save*(..))"/>
       <!-- 设置before advice, 用checkAspect中的一个方法,并定位到相位的切入点pointcut -->
       <aop:before method="checkUser" pointcut-ref="allSaveMethod"/>
   </aop:aspect>
</aop:config>

</beans>

三、测试用例:

public void testAspect(){
   BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
   IUserManager userManager = (IUserManager) factory.getBean("userManager");
   userManager.saveUser("cat", "123");
   userManager.delUser(1);
   userManager.updateUser(1);
}

输出结果:

=======CheckAspect.checkUser()===========
=====UserManagerImpl.saveUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========

四、Advice中可以加入JoinPoint参数,内含有代理类的方法的方法名和参数数组

import org.aspectj.lang.JoinPoint ;

/*
* 定义通知advice(before型),标识在哪个切入点(allSaveMethod),织入(weaver)此方法
* JoinPoint 内含代理类的参数和方法
*/
public void checkUser(JoinPoint joinPoint ){
   Object[] args = joinPoint.getArgs();
   for(int i=0; i<args.length; i++){
    System.out.println("参数" + i + "=" + args[i]);
   }
   System.out.println("代理类的方法:" + joinPoint.getSignature().getName());
   System.out.println("=======CheckAspect.checkUser()===========");
}

输入结果:

参数0=cat
参数1=123
代理类的方法:saveUser
=======CheckAspect.checkUser()===========

=====UserManagerImpl.saveUser()===========
=====UserManagerImpl.delUser()===========
=====UserManagerImpl.updateUser()===========

=======================================

注:Aspect默认情况下不用实现接口,但对于目标对象(UserManagerImpl.java),在默认情况下必须实现接口;
如果没有实现接口必须引入CGLIB库

==================================

Spring AOP 用户可能会经常使用 execution pointcut designator。执行表达式的格式如下:

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

除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外,所有的部分都是可选的。 返回类型模式决定了方法的返回类型必须依次匹配一个连接点。 你会使用的最频繁的返回类型模式是 * ,它代表了匹配任意的返回类型。 一个全称限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。 你可以使用 * 通配符作为所有或者部分命名模式。 参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。 模式 (*) 匹配了一个接受一个任何类型的参数的方法。 模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型。 请参见AspectJ编程指南的 Language Semantics 部分。

下面给出一些常见切入点表达式的例子。

  • 任意公共方法的执行:

    execution(public * *(..))
  • 任何一个以“set”开始的方法的执行:

    execution(* set*(..))
  • AccountService 接口的任意方法的执行:

    execution(* com.xyz.service.AccountService.*(..))
  • 定义在service包里的任意方法的执行:

    execution(* com.xyz.service.*.*(..))
  • 定义在service包或者子包里的任意方法的执行:

    execution(* com.xyz.service..*.*(..))
  • 在service包里的任意连接点(在Spring AOP中只是方法执行) :

    within(com.xyz.service.*)
  • 在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :

    within(com.xyz.service..*)
  • 实现了 AccountService 接口的代理对象的任意连接点(在Spring AOP中只是方法执行) :

    this(com.xyz.service.AccountService)

    'this'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得代理对象可以在通知体内访问到的部分。

  • 实现了 AccountService 接口的目标对象的任意连接点(在Spring AOP中只是方法执行) :

    target(com.xyz.service.AccountService)

    'target'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得目标对象可以在通知体内访问到的部分。

  • 任何一个只接受一个参数,且在运行时传入的参数实现了 Serializable 接口的连接点 (在Spring AOP中只是方法执行)

    args(java.io.Serializable)

    'args'在binding form中用的更多:- 请常见以下讨论通知的章节中关于如何使得方法参数可以在通知体内访问到的部分。

    请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)) : args只有在动态运行时候传入参数是可序列化的(Serializable)才匹配,而execution 在传入参数的签名声明的类型实现了 Serializable 接口时候匹配。

  • 有一个 @Transactional 注解的目标对象中的任意连接点(在Spring AOP中只是方法执行)

    @target(org.springframework.transaction.annotation.Transactional)

    '@target' 也可以在binding form中使用:请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。

  • 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点(在Spring AOP中只是方法执行)

    @within(org.springframework.transaction.annotation.Transactional)

    '@within'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。

  • 任何一个执行的方法有一个 @Transactional annotation的连接点(在Spring AOP中只是方法执行)

    @annotation(org.springframework.transaction.annotation.Transactional)

    '@annotation' 也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。

  • 任何一个接受一个参数,并且传入的参数在运行时的类型实现了 @Classified annotation的连接点(在Spring AOP中只是方法执行)

    @args(com.xyz.security.Classified)

    '@args'也可以在binding form中使用:- 请常见以下讨论通知的章节中关于如何使得annotation对象可以在通知体内访问到的部分。

    ================================================

    出现error at ::0 can't find referenced pointcut...这样的错误原因是:如果你用的JDK版本是1.6的话,而引用的aspectjrt.jar是spring-2.0中包含的jar包的情况下就会报这样的错误。
    解决的办法就是下载最新的aspectjrt的jar包即可aspectj-1.6.6.jar

分享到:
评论

相关推荐

    SpringAOP的注解配置

    SpringAOP的注解配置完成切面的编程,完成execution,annotation两种表达式的实例Ddemo

    aop-log-annotation:基于Log4j+SpringAOP+Annotation的可注解日志切面组件

    基于Log4j+SpringAOP+Annotation的可注解日志切面组件 使用方式 @Log(logAfter = true, logBefore = true) public returntype methodName(params) 测试类com.liam.aop.aspect.test.AopLogAnnotationTest 测试输出 ...

    spring中自定义注解(annotation)与AOP中获取注解

    spring中自定义注解(annotation)与AOP中获取注解.通过实例演示自定义注解。

    spring-aop-annotation-log-all

    这里zip压缩包囊括了学习Spring过程中用到的所有的jar包; 有: ...spring-web-4.1.2.RELEASE.jar //aop注解需要 对于Spring环境的插件,你们可以到Eclipase中的help&gt;Eclipse marketplace...去搜索安装

    【Spring AOP】@Aspect结合案例详解(一): @Pointcut使用@annotation + 五种通知

    在微服务流行的当下,在使用SpringCloud/Springboot框架开发中,AOP使用的非常广泛,尤其是@Aspect注解方式当属最流行的,不止功能强大,性能也很优秀,还很舒心!所以本系列就结合案例详细介绍@Aspect方式的切面的...

    应用Spring AOP(六)-------Annotation注解配置方式

    NULL 博文链接:https://tonl.iteye.com/blog/1966822

    【Spring AOP】@Aspect结合案例详解(二): @Pointcut使用@within和within

    在微服务流行的当下,在使用Spring Cloud / Spring Boot框架开发中,AOP使用的非常广泛,尤其是@Aspect注解方式当属最流行的,不止功能强大,性能也很优秀,还很舒心!所以本系列就结合案例详细介绍@Aspect方式的切...

    Spring AOP配置源码

    两行为开启spring的注解配置 &lt;aop:aspect id="aspect" ref="logIntercepter"&gt; 引入具体的AOP操作类 &lt;aop:pointcut expression="execution(* com.spring.service..*(..))" id="pointCut"/&gt;声明一个切入点,注意...

    详解Spring Aop实例之AspectJ注解配置

    本篇文章主要介绍了详解Spring Aop实例之AspectJ注解配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Spring注解 - 52注解 - 原稿笔记

    注解包含: 拦截器 , 过滤器 , 序列化 , @After , @AfterReturning , @AfterThrowing , @annotation , @Around , @Aspect , @Autowired , @Bean , @Before , @Component , @ComponentScan , @ComponentScans , @...

    Spring的学习笔记

    (二) annotation注解方式的SessionFactory 30 二、 引入hibernate所需要使用的jar 31 (一) 基本jar 31 (二) 加入annotation功能的jar包 31 (三) 搭建日志环境并配置显示DDL语句jar包 31 三、 Spring整合hibernate3...

    spring-boot-annotation-spel.zip

    SpringBoot 自定义注解,属性支持SPEL表达式。介绍了SPEL表达式的解析

    spring2.5 学习笔记

    (二) annotation注解方式的SessionFactory 30 二、 引入hibernate所需要使用的jar 31 (一) 基本jar 31 (二) 加入annotation功能的jar包 31 (三) 搭建日志环境并配置显示DDL语句jar包 31 三、 Spring整合hibernate3...

    高效的缓存管理解决方案AutoLoadCache.zip

    设计思想及原理使用方法注解(Annotation)说明表达式的应用缓存删除注意事项缓存管理页面与Spring Cache的区别源码阅读已经实现基于aspectj,代码在com.jarvis.cache.aop.aspectj.AspectjAopInterceptor。想通过...

    详解SpringBoot AOP 拦截器(Aspect注解方式)

    主要介绍了详解SpringBoot AOP 拦截器 Aspect,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    Spring.3.x企业应用开发实战(完整版).part2

    《Spring3.x企业应用开发实战》是在《精通Spring2.x——企业应用开发详解》的基础上,经过历时一年的重大调整改版而成的,本书延续了上一版本追求深度,注重原理,不停留在技术表面的写作风格,力求使读者在熟练使用...

    Spring Framewor开发手册

    2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut element)...

    Spring中文帮助文档

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...

    Android AOP 注解详解及简单使用实例(三)

    Android AOP注解Annotation详解(一) Android AOP之注解处理解释器详解(二) Android AOP 注解详解及简单使用实例(三) 一、简介 在Android 里面 注解主要用来干这么几件事: 和编译器一起给你一些提示警告信息...

    spring2.5.chm帮助文档(中文版)

    2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut ...

Global site tag (gtag.js) - Google Analytics