`
zhaohaolin
  • 浏览: 1019996 次
  • 性别: 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

分享到:
评论

相关推荐

    spring aop实例annotation方法实现

    本实例将详细探讨如何通过注解(Annotation)来实现Spring AOP的方法拦截。 一、Spring AOP基础 Spring AOP是Spring框架的一部分,它提供了一种在运行时织入横切关注点(如日志、事务管理等)到目标对象的能力。AOP...

    springboot spring aop 拦截器注解方式实现脱敏

    总结一下,通过上述步骤,我们已经在Spring Boot应用中利用Spring AOP和注解方式实现了数据脱敏。这个拦截器可以在不修改原有业务代码的情况下,确保敏感信息在响应给客户端之前得到处理,提高了应用的安全性。同时...

    spring aop注解版

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点问题,如日志、事务管理等。在本主题中,我们将深入探讨Spring AOP的注解版,它是基于Java注解的...

    Spring AOP + AspectJ annotation example

    AspectJ注解是与Spring AOP集成的一种方式,使得我们可以直接在Java类和方法上定义切面。例如,`@Aspect`注解标记一个类为切面,`@Before`、`@After`、`@Around`、`@AfterReturning`和`@AfterThrowing`分别用于定义...

    SpringAOP的注解配置

    在Spring AOP中,我们可以通过注解配置来实现切面编程,从而简化代码并提高可维护性。 首先,我们需要了解Spring AOP中的核心概念: 1. **切面(Aspect)**:切面是关注点的模块化,它包含了横切关注点(如日志)和...

    以注解方式模拟Spring IoC AOP

    Spring提供了两种主要的AOP实现方式:基于代理(Proxy-based)和基于注解(Annotation-based)。 - **基于代理的AOP**:Spring使用JDK动态代理或CGLIB动态代理创建目标对象的代理,代理对象在调用目标方法前后执行...

    用注解的方式进行SpringAOP开发

    本篇我们将深入探讨如何使用注解的方式来实现Spring AOP开发。 ### 一、注解基础 在Spring AOP中,主要使用以下几种注解: 1. `@Aspect`:定义一个切面类,切面是AOP的核心,包含通知(advisors)和切点...

    Spring aop 性能监控器

    可以查看Spring AOP的实现,尤其是`org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator`和`org.springframework.aop.aspectj.AspectJExpressionPointcut`这两个类,它们分别处理了...

    Spring_Annotation_AOP

    在本资料"Spring_Annotation_AOP"中,我们将深入探讨Spring框架如何利用注解实现AOP,以及其背后的原理和实践应用。 面向切面编程(AOP)是一种编程范式,旨在提高代码的可维护性和可重用性,通过将关注点分离,...

    理解Spring AOP实现与思想 案例代码

    2. **Spring AOP实现方式** - **代理模式**:Spring AOP使用两种代理方式,JDK动态代理和CGLIB代理。如果目标类实现了接口,Spring会使用JDK动态代理;如果没有实现接口,Spring会使用CGLIB代理生成子类。 - **JDK...

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

    Spring AOP提供了两种主要的方式来实现这一点:基于XML的配置和基于注解的配置。 对于基于XML的配置,我们需要在`&lt;aop:config&gt;`标签内定义切点表达式和通知(advice),如下: ```xml &lt;aop:config&gt; &lt;aop:pointcut...

    spring aop 注解例子

    本例子就是一个使用 Spring AOP 注解实现的项目,旨在展示如何在简单的环境中应用这一特性。 1. **AOP 基础概念** - **切面(Aspect)**: 包含一组相关功能的模块,这些功能在多个对象中都可能被用到,比如日志、...

    Spring AOP面向方面编程原理:AOP概念

    Spring AOP支持多种方式来定义切入点,包括但不限于方法名、类名、注解等。 5. **引入(Introduction)**:允许向被通知对象添加新的接口实现或者新的方法。例如,可以使用引入让任何对象实现`IsModified`接口,...

    Spring AOP 常用的四种实现方式

    本篇文章将深入探讨Spring AOP的四种常见实现方式。 一、基于接口的代理(Interface-Based Proxy) 这是Spring AOP最基础的实现方式,适用于目标对象实现了特定接口的情况。Spring会创建一个代理对象,该对象实现...

    spring aop xml 实例

    Spring AOP主要通过两种方式实现:XML配置和注解。本实例主要探讨的是使用XML配置的方式来实现AOP。XML配置虽然相比注解方式略显繁琐,但它提供了更大的灵活性,尤其是在需要对多个类或方法应用相同通知(Advice)时...

    Spring AOP 常用的四种实现方式的代码

    本篇文章将详细讲解Spring AOP的四种常见实现方式,以帮助开发者更好地理解和运用这一功能。 一、基于接口的代理(Interface-Based Proxy) 这是Spring AOP的默认实现方式,适用于目标对象实现了接口的情况。Spring...

    spring的Annotation注解.

    ### Spring框架中的Annotation注解详解 #### 一、Spring与Annotation的基本概念 Spring框架通过引入Annotation,极大地简化了Java开发中的依赖注入(Dependency Injection, DI)和面向切面编程(AOP)的过程。...

    spring aop的demo

    切面可以通过两种方式实现:基于注解(Annotation-based)和基于XML配置。在本Demo中,我们可能会看到使用注解的方式来创建切面,例如使用`@Aspect`来声明一个类作为切面,`@Before`、`@After`、`@Around`等来定义...

    springboot+aspect实现springaop拦截指定方法.zip

    SpringBoot结合AspectJ实现SpringAOP拦截指定方法的知识点涵盖了多个方面,这包括Spring AOP的基本概念、SpringBoot的应用、切点(Pointcut)与通知(Advice)的定义、自定义注解以及AspectJ的使用。以下是这些知识...

    SpringAOP.zip

    Spring AOP,全称为Aspect Oriented Programming,是Spring框架中的一个重要模块,主要负责处理系统中的...文件"5.SpringAOP_01"和"6.SpringAOP_02"很可能是课程的分阶段内容,涵盖了从基础概念到进阶实践的详细讲解。

Global site tag (gtag.js) - Google Analytics