zoukankan      html  css  js  c++  java
  • Spring AspectJ AOP 完整示例

    http://outofmemory.cn/java/spring/AOP/aop-aspectj-example-before-after-AfterReturning-afterThrowing-around 

    我们介绍了spring aop相关的概念和aop注入表达式的示例,这里我们用一个完整的例子演示spring aspectj aop的使用。

    首先新建一个maven项目,在项目的pom.xml中添加spring aop相关的依赖项:

    如下是完整的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.outofmemory</groupId>
    	<artifactId>spring-aop-aspect</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>spring-aop-aspect</name>
    	<url>http://maven.apache.org</url>
    	<properties>
    		<spring.version>3.1.1.RELEASE</spring.version>
    	</properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-core</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-context</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aop</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjrt</artifactId>
    			<version>1.6.12</version>
    		</dependency>
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>1.6.12</version>
    		</dependency>
    		<dependency>
    			<groupId>cglib</groupId>
    			<artifactId>cglib</artifactId>
    			<version>2.2</version>
    		</dependency>
    	</dependencies>
    </project>

    在maven中我们引入了spring aop相关的依赖,aspectj相关的包有两个,cglib是必须的。

    下面我们在项目中新建一个Service类PersonService,它是业务代码,是我们AOP注入的目标类:

    package cn.outofmemory.spring_aop_aspect;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class PersonService {
    
    	public void addPerson(String personName) {
    		System.out.println("add person " + personName);
    	}
    	
    	public boolean deletePerson(String personName) {
    		System.out.println("delete person " + personName) ;
    		return true;
    	}
    	
    	public void editPerson(String personName) {
    		System.out.println("edit person " + personName);
    		throw new RuntimeException("edit person throw exception");
    	}
    	
    }

    PersonService类中定义了三个方法,addPerson方法无返回值,而deletePerson方法有返回值,而editPerson方法抛出运行时的异常。

    下面我们看Aspect类:

    package cn.outofmemory.spring_aop_aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class SimpleAspect {
    	@Pointcut("execution(* cn.outofmemory.spring_aop_aspect.*Service*.*(..))")
    	public void pointCut() {
    	}
    
    	@After("pointCut()")
    	public void after(JoinPoint joinPoint) {
    		System.out.println("after aspect executed");
    	}
    
    	@Before("pointCut()")
    	public void before(JoinPoint joinPoint) {
    		//如果需要这里可以取出参数进行处理
    		//Object[] args = joinPoint.getArgs();
    		System.out.println("before aspect executing");
    	}
    
    	@AfterReturning(pointcut = "pointCut()", returning = "returnVal")
    	public void afterReturning(JoinPoint joinPoint, Object returnVal) {
    		System.out.println("afterReturning executed, return result is "
    				+ returnVal);
    	}
    
    	@Around("pointCut()")
    	public void around(ProceedingJoinPoint pjp) throws Throwable {
    		System.out.println("around start..");
    		try {
    			pjp.proceed();
    		} catch (Throwable ex) {
    			System.out.println("error in around");
    			throw ex;
    		}
    		System.out.println("around end");
    	}
    
    	@AfterThrowing(pointcut = "pointCut()", throwing = "error")
    	public void afterThrowing(JoinPoint jp, Throwable error) {
    		System.out.println("error:" + error);
    	}
    }

    SimpleAspect类中的第一个方法是pointCut()方法,此方法无任何执行内容,只有一个@Pointcut的注解,其他方法都会引用这个注解中指定的pointcut表达式。

    其他几个方法是各种Advice类型的方法实现,在这些方法中都可以通过JoinPoint实例来获得方法执行的上下文信息,参数信息。需要注意AfterReturning和AfterThrowing,After三种不同Advice的执行顺序。

    有了spring框架和aspectj以及cglib的支持,我们只需要实现上面两个类就可以使用spring aop的功能了,下面我们看下如何在spring的配置文件中配置spring aop。

    <?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"
           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.1.xsd">
        <aop:aspectj-autoproxy />
        <context:component-scan base-package="cn.outofmemory" /> 
    </beans>

    注意在beans节点中需要指定aop命名空间,一家chemaLocation地址,启用aop只需要添加<aop:aspectj-autoproxy/>就可以了。<context:component-scan/>节点用来指定自动扫描bean的命名空间

    最后我们要测试下aop的效果,需要新建一个App类作为程序的入口类。

    package cn.outofmemory.spring_aop_aspect;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    /**
     * Hello world!
     *
     */
    public class App 
    {
        public static void main( String[] args )
        {
        	ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
        	PersonService personService = appContext.getBean(PersonService.class);
        	String personName = "Jim";
        	personService.addPerson(personName);
        	personService.deletePerson(personName);
        	personService.editPerson(personName);
        	((ClassPathXmlApplicationContext)appContext).close();
        }
    }

    这个类中我们初始化了ApplicationContext,然后从中得到PersonService的实例,并执行其addPerson,deletePerson,editPerson方法,最后关闭ApplicationContext。

    其执行结果如下:

    before aspect executing
    around start..
    add person Jim
    after aspect executed
    around end
    afterReturning executed, return result is null
    -------------------------------------
    before aspect executing
    around start..
    delete person Jim
    after aspect executed
    around end
    afterReturning executed, return result is null
    ----------------------------------------
    before aspect executing
    around start..
    edit person Jim
    after aspect executed
    error in around
    error:java.lang.RuntimeException: edit person throw exception
    Exception in thread ...

    从上面执行结果可以看到我们要执行的Before,around,after以及around,afterReturning,afterThrowing都正常的执行了。

    最后给出此示例项目的完整代码:spring-aop-aspect.zip

  • 相关阅读:
    Java8新特性Function、BiFunction使用
    Java8 stream用法-备忘录
    springboot使用过滤器Filter
    dockerfile命令说明及使用
    RestTemplate对象,进行get和post简单用法
    Jackson动态处理返回字段
    springboot-jjwt HS256加解密(PS:验证就是解密)
    SpringBoot2.1.3修改tomcat参数支持请求特殊符号
    mysql存储过程 带参数 插入 操作
    性能测试如何计算设置并发数
  • 原文地址:https://www.cnblogs.com/exe19/p/5392508.html
Copyright © 2011-2022 走看看