spring之aop编程——基于注解、xml配置文件方式

AOP(Aspect Oriented Programming),是面向切面编程的技术。AOP基于IoC基础,是对OOP的有益补充。spring中AOP的配置方式有2种方式:xml配置和AspectJ注解方式。

一、xml配置的方式:

1、service接口和服务类:

package cn.edu.nuc.SpringTest.service;

public interface DemoService {

public String sayHello(String name) ;

}

package cn.edu.nuc.SpringTest.service.impl;

import org.springframework.stereotype.Service;

import cn.edu.nuc.SpringTest.common.anno.Permission;

import cn.edu.nuc.SpringTest.service.DemoService;

@Service

public class DemoServiceImpl implements DemoService{

@Permission(value="no")

public String sayHello(String name) {

System.out.println("hello word.........."+name);

return "返回值";

}

}

2、切面类开发:

package cn.edu.nuc.SpringTest.interceptor;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.Signature;

import org.aspectj.lang.reflect.MethodSignature;

import cn.edu.nuc.SpringTest.common.anno.Permission;

public class MyInterceptor1 {

public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{

System.out.println("环绕通知进入方法----");

Object object=pjp.proceed();

System.out.println("环绕通知退出方法------");

return object;

}

//后置通知(不需要获取返回值)

public void doAfterReturning(JoinPoint jp,String name,Object rvt){

System.out.println("后置通知,参数:"+name);

System.out.println("后置返回:"+rvt);

}

public void doAfterThrowing(JoinPoint jp,Throwable ex){

System.out.println("例外通知~~~~~~~~~~~~~~~~~~~");

System.out.println("method " + jp.getTarget().getClass().getName()

+ "." + jp.getSignature().getName() + " throw exception");

System.out.println(ex.getMessage()+ex.toString());

}

//最终通知

public void doAfter(JoinPoint jp,String name){

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

}

//前置通知(不需要获取输入参数)

public void doAccessCheck(JoinPoint jp){

Object[] args = jp.getArgs();

Signature signature = jp.getSignature();

MethodSignature methodSignature = (MethodSignature)signature;

Method targetMethod = methodSignature.getMethod();

if (targetMethod.isAnnotationPresent(Permission.class)) {

Permission annotation = targetMethod.getAnnotation(Permission.class);

System.out.println("我是anno:"+annotation.value());

}

System.out.println("前置通知--------"+",参数:"+args[0]);

}

}

3、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:context="http://www.springframework.org/schema/context"

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

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

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

http://www.springframework.org/schema/aop

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

http://www.springframework.org/schema/context

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

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<context:component-scan base-package="cn.edu.nuc.SpringTest"/>

<bean id="myInterceptor11" class="cn.edu.nuc.SpringTest.interceptor.MyInterceptor1"></bean>

<aop:config proxy-target-class="true">

<aop:aspect id="asp1" ref="myInterceptor11">

<aop:pointcut expression="execution (* cn.edu.nuc.SpringTest.service..*.*(..))"  id="mycut"/>

<aop:before method="doAccessCheck" pointcut="execution (* cn.edu.nuc.SpringTest.service..*.*(..))" />

<aop:after method="doAfter" pointcut="execution (* cn.edu.nuc.SpringTest.service..*.*(..)) and args(name)" />

<aop:after-returning method="doAfterReturning" pointcut="execution (* cn.edu.nuc.SpringTest.service..*.*(..)) and args(name)" returning="rvt" />

<aop:around method="doBasicProfiling" pointcut="execution (* cn.edu.nuc.SpringTest.service..*.*(..))" />

<aop:after-throwing method="doAfterThrowing" pointcut-ref="mycut" throwing="ex"/>

</aop:aspect>

</aop:config>

</beans>

4、测试:

public class App  {

public static void main( String[] args ) {

String[] fileUrl = new String[]{"classpath*:applicationContext.xml"};

ApplicationContext appContext = new ClassPathXmlApplicationContext(fileUrl);

DemoServiceImpl ser = appContext.getBean(DemoServiceImpl.class);

ser.sayHello("刘晓111");

}

}

注意点:

1)后置返回通知方法中,如果要获得切入点方法返回值,需要配置returning,且需要保持与后置返回通知方法的参数名一致;

2)后置异常通知方法中,如果要获得切入点方法异常,需要配置throwing,且保持与方法中异常的参数名一致;

3)在xml中,可以通过<aop:pointcut… 配置多个切入点,然后在切面类中的前置、后置、环绕、例外通知中使用不同的切入点;

4)在前置、后置、例外通知的方法中,JoinPoint要 作为第一个参数,(环绕通知使用的是ProceedingJoinPoint),通过JoinPoint 配合反射可以获得切入点的类、方法、注解等信息;(这里注意,JoinPoint 一定要放在第一个参数的位置,当JoinPoint 和切入点方法参数、切入点方法返回值、例外对象放在一起时,如果JoinPoint 不在第一个参数位置,那么spring会报一个无法绑定切入点的错误error at ::0 formal unbound in pointcut。例如:public
void doAfterReturning(JoinPoint jp,String name,Object rvt)中,既有JoinPoint 也有切入点方法参数、还有切入点方法返回,JoinPoint 一定放在第一位)

5)切面类的通知方法中获取切入点方法的参数:

1.在通知方法中,可以通过JoinPoint 获取切入点方法的所有参数;

2.可以在xml中配置and args(name) ,name要和切入点方法参数名、通知方法的参数名一致,这样就可以在通知方法中的参数获取切入点方法的参数了;

补充:切面类是指附加功能的类,例如 MyInterceptor1 ,通知方法是切面类中,aop规定好的前置、后置...标记的方法;

切入点类,是要被切入的业务类,如DemoServiceImpl ,切入点方法是切入点类中,被切入的方法。

二、注解方式:

1、service接口和服务类:(同上)

2、切面类开发:

packagecn.edu.nuc.SpringTest.interceptor;

importjava.lang.reflect.Method;

importorg.aspectj.lang.JoinPoint;

importorg.aspectj.lang.ProceedingJoinPoint;

importorg.aspectj.lang.Signature;

importorg.aspectj.lang.annotation.After;

importorg.aspectj.lang.annotation.AfterReturning;

importorg.aspectj.lang.annotation.AfterThrowing;

importorg.aspectj.lang.annotation.Around;

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Before;

importorg.aspectj.lang.annotation.Pointcut;

importorg.aspectj.lang.reflect.MethodSignature;

importorg.springframework.stereotype.Component;

importcn.edu.nuc.SpringTest.common.anno.Permission;

@Component

@Aspect

public classMyInterceptor {

//切入点要拦截的类,声明一个切入点,切入点的名称其实是一个方法

@Pointcut("execution(* cn.edu.nuc.SpringTest.service..*.*(..))")

privatevoid anyMethod(){}

//声明一个切入点,切入点的名称其实是一个方法

@Pointcut(value="execution(* cn.edu.nuc.SpringTest.service..*.*(java.lang.String)) && args(name)")

privatevoid nameParameMethod(String name){}

@Around("anyMethod()")

publicObject doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{

System.out.println("环绕通知进入方法");

Objectobject=pjp.proceed();

System.out.println("环绕通知退出方法");

returnobject;

}

//后置通知(不需要获取返回值)

//        @AfterReturning("anyMethod()")

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

publicvoid doAfterReturning(JoinPoint jp,String result){

Object[]args = jp.getArgs();

Objecttarget = jp.getTarget();

Signaturesignature = jp.getSignature();

MethodSignaturemethodSignature = (MethodSignature)signature;

Method targetMethod =methodSignature.getMethod();

boolean b =targetMethod.isAnnotationPresent(Permission.class);

if (b) {

Permission perm =targetMethod.getAnnotation(Permission.class);

String value =perm.value();

System.out.println("@@@@@@@@@@@@@@@@@"+value);

}

System.out.println("======="+signature.getName()+";"+jp.getThis().toString());

System.out.println("后置通知:"+args[0]+target.toString()+";返回值:"+result);

}

//@AfterThrowing("anyMethod()")

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

publicvoid doAfterThrowing(Exception e){

System.out.println("例外通知:");

}

//最终通知

@After(value="anyMethod()")

publicvoid doAfter(JoinPoint jp){

Object[]args = jp.getArgs();

System.out.println("最终通知:================="+args[0]);

}

//前置通知(不需要获取输入参数)

@Before("nameParameMethod(name)")//第一个参数为切入点的名称,第二个是测试获取输入参数,此处为string类型的,参数名称与方法中的名称相同,如果不获取输入参数,可以不要

//@Before("anyMethod()")//第一个参数为切入点的名称

public void doAccessCheck(JoinPoint jp,String name){

System.out.println("前置通知:"+name);

}

}

3、配置文件:

<?xmlversion="1.0" encoding="UTF-8"?>

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

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

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

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

http://www.springframework.org/schema/aop

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

http://www.springframework.org/schema/context

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

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<context:component-scanbase-package="cn.edu.nuc.SpringTest"/>

<!-- 注解方式的aop -->

<aop:aspectj-autoproxy  proxy-target-class="true"/>

</beans>

注:需要使用<aop:aspectj-autoproxy  proxy-target-class="true"/>
 开启注解aop功能,如果使用了ioc,那么一定要加上proxy-target-class="true"

4、测试类:(同上)

注意点:

1)后置返回通知方法中,如果要获得切入点方法返回值,需要在AfterReturning 注解中加上returning,且需要保持与后置返回通知方法的参数名一致;

2)后置异常通知方法中,如果要获得切入点方法异常,需要在AfterThrowing注解中加上throwing,且保持与方法中异常的参数名一致;

3)同样,在通知方法中,JoinPoint要 作为第一个参数,例如:public void doAccessCheck(JoinPoint jp,String name)中;

4)切面类的通知方法中获取切入点方法的参数:

1.在通知方法中,可以通过JoinPoint 获取切入点方法的所有参数;

2.在切面类的注解上配置andargs(name),name要和切入点方法参数名、通知方法的参数名一致,这样就可以在通知方法中的参数获取切入点方法的参数了;

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.edu.nuc</groupId>
  <artifactId>SpringTest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>SpringTest</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <org.springframework.version>3.1.1.RELEASE</org.springframework.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <version>${org.springframework.version}</version>
	</dependency>
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-orm</artifactId>
	    <version>${org.springframework.version}</version>
	</dependency>
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-test</artifactId>
	    <version>${org.springframework.version}</version>
	    <type>jar</type>
	    <scope>test</scope>
	</dependency>
	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjweaver</artifactId>
	    <version>1.8.2</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-core</artifactId>
		<version>2.2.3</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.2.3</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-annotations</artifactId>
		<version>2.2.3</version>
	</dependency>

	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>2.2</version>
	</dependency>

  </dependencies>

</project>

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 19:39:04

spring之aop编程——基于注解、xml配置文件方式的相关文章

spring AOP (包含基于注解和配置文件两种方式)

spring AOP?面向切面编程,区别于面向对象编程OOP AspectJ: 是Java社区里面最完整最流行的AOP框架,下面就用aspectJ来上例子 一.基于注解方式 步骤如下: 引入jar包(spring的必要jar包 以及aspectj的jar包) 业务方法HelloworldService (类上加上注解@Component,放入到spring ioc容器中) 切面LogingAop (类上加上注解@Component使其加入到ioc容器中,还需要注解@Aspect,使其成为一个切面

spring学习2:基于注解+xml实现ioc和依赖注入

spring学习2:基于注解+xml实现ioc和依赖注入 一.在spring配置文件中开启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&qu

spring学习5:基于注解实现spring的aop

目录 spring学习5:基于注解实现spring的aop 一.基于注解+xml实现 1.1 在配置文件中开启spring对注解aop的支持 1.2 把通知类用注解配置到容器中,并用注解声明为切面 1.3 定义切入点表达式 1.4 定义通知 二.基于纯注解实现 三.多个aop的执行顺序 1.xml配置 2.注解配置 3.注意 spring学习5:基于注解实现spring的aop 上一节学习了spring aop的基本概念和如何基于xml配置来实现aop功能.这一节来学习下如何用注解实现aop 一

SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释

SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释 2016-04-14 23:40 13030人阅读 评论(2) 收藏 举报 分类: SSM(7) 这几天一直在整合SSM框架,虽然网上有很多已经整合好的,但是对于里面的配置文件并没有进行过多的说明,很多人知其然不知其所以然,经过几天的搜索和整理,今天总算对其中的XML配置文件有了一定的了解,所以拿出来一起分享一下,希望有不足的地方大家批评指正~~~ 首先   这篇文章暂时只对框架中所要用到的配置文件进行解

Spring MVC 中的基于注解的 Controller【转】

原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响应请求.实际上,ControllerClassNameHandlerMapping, MultiActionController 和选择恰当的 methodNameResolver(如 InternalPathMetho

spring相关—AOP编程—数学计算器情景示例讲解(包含注解配置AOP与XML配置AOP)

1.数学计算器 ①数学计算器接口[MathCalculator]            public void add(int i,int j);     public int sub(int i,int j);     public int multi(int i,int j);     public void divide(int i,int j);    ②提供简单实现:加减乘除运算[EasyImpl]    ③在简单实现的基础上让每一个计算方法都能够打印日志[LoginImpl]    

Spring进阶之路(11)-使用Aspectj切面配置和XML配置文件方式实现切面编程

异常 在使用的时候,遇到了部分的异常,我用的是最新的Spring版本,Spring-4.2.5版本的,首先确保你的配置文件中引入了下面红色部分. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <span style="color:#ff0000;">

【Spring】AOP之基于XML配置总结与案例

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.AOP的一些概念 AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但

spring基于注解的配置文件

1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.o