Spring aop使用

前言:aop即Aspect Oriented-Programming,面向切面编程是对面向对象编程思想的补充,在众多的aop资料介绍中,我推荐大家可查看Spring Aop详尽教程Spring Aop实例

我这里主要通过实例来简单介绍Spring aop在Springboot中的使用及自己踩的小坑

  1. 搭建springboot环境,直接附上一份pom.xml配置文件,此份文件结合了Mybatis+mysql


4.0.0

<groupId>com.jing.sprintboot</groupId>
<artifactId>TestSpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>TestSpringBoot</name>
<url>https://mvnrepository.com</url>
<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<spring.version>4.2.3.RELEASE</spring.version>
	<spring.boot.version>1.3.0.RELEASE</spring.boot.version>
	<tomcat.version>8.0.28</tomcat.version>
</properties>

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.0.RELEASE</version>
</parent>
<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>3.8.1</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.1.0</version>
		<scope>provided</scope><!-- 编译需要而发布不需要的jar包 -->
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
		<version>${spring.boot.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-freeMarker</artifactId>
		<version>1.3.0.RELEASE</version>
	</dependency>
	<!-- mybatis -->
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.1.1</version>
	</dependency>
	<!-- mysql -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<version>${spring.boot.version}</version>
			<executions>
				<execution>
					<goals>
						<goal>repackage</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
	<defaultGoal>compile</defaultGoal>
</build>
```
  1. 添加aop环境,主要是添加aspectjweaver.jar依赖

    <!-- aop -->
    	<dependency>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-aop</artifactId>
    	</dependency>
    
    
  2. aop示例代码如下:

    package com.jing.springboot.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class RequestAopInterceptor {
        private static final Logger REQ_LOGGER = LoggerFactory.getLogger(RequestAopInterceptor.class);
    
    // 匹配语法为:注解 修饰符 返回值类型 类名 方法名(参数列表) 异常列表 具体可查看
    // http://blog.csdn.net/wangpeng047/article/details/8556800
    @Pointcut("execution(* com.jing.springboot.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void interceptor() {
    
    }
    
    // 指定声明的pointcut
    @Before("interceptor()")
    public void before() {
    	REQ_LOGGER.info("before the requestMapping");
    }
    
    @After("interceptor()")
    public void after() {
    	REQ_LOGGER.info("requestMapping is over");
    }
    
    @AfterReturning(pointcut = "interceptor()", returning = "result")
    public void doAfterReturing(Object result) {
    	REQ_LOGGER.info("请求返回的信息为: " + result);
    }
    
    @Around("interceptor()")
    public Object doRound(ProceedingJoinPoint joinPoint) {
    	Object result = null;
    	REQ_LOGGER.info("doRound before");
    	try {
    		result = joinPoint.proceed();
    	} catch (Throwable e) {
    		e.printStackTrace();
    	}
    	REQ_LOGGER.info("doRound after");
    	return result;
    }
    

}
```

  1. 注意@Around注解,其返回值是Object,不可写为void,不然将会导致前台获取数据不得的情况
  2. 罗列下Spring aop中的@Before@After@AfterReturning@AfterThrowing@Around的执行顺序
    • @Around前半部分
    • @Before代码逻辑
    • @Around后半部分
    • @After代码逻辑
    • @AfterReturing/@AfterThrowing代码逻辑,前者是在正确返回时触发,后者在出现异常时触发,其中的触发条件也可根据参数来指定,具体可见前言的链接博客
  3. 回到示例,写个Hello World
    package com.jing.springboot.controller;
    
    import javax.annotation.Resource;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.jing.springboot.model.Person;
    import com.jing.springboot.mysql.mapper.UserDao;
    
    
    //@author jingsir
    @RestController
    @RequestMapping(value = "/hello")
    public class HelloWorldControl {
    
    @Resource
    private UserDao userDao;
    
    public HelloWorldControl() {
    }
    
    @RequestMapping(value = "", method = RequestMethod.GET)
    public Person returnPerson() {
    	Person person = new Person();
    	person.setName("jingtj");
    	person.setAge(23);
    	return person;
    }
    
    //可测试@AfterReturning的返回值参数
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String hello() {
    	return "hello world";
    }
    
    //此段可忽略
    @RequestMapping(value = "/freemarker")
    public ModelAndView helloFreemaker() {
    	ModelAndView indexView = new ModelAndView("index");
    	indexView.addObject("user", "jingsir");
    	return indexView;
    }
    

}

```
* 其中在application.properties的配置信息如下:
```

server.port=9901
server.contextPath=/springboot
* 浏览器访问localhost:9901/springboot/hello/便可,查看后台控制台的内容为(对照上述的第五点执行顺序便可明白):
2017-03-19 20:25:44.074 INFO 502 --- [nio-9901-exec-3] c.j.s.aop.RequestAopInterceptor : doRound before
2017-03-19 20:25:44.074 INFO 502 --- [nio-9901-exec-3] c.j.s.aop.RequestAopInterceptor : before the requestMapping
2017-03-19 20:25:44.074 INFO 502 --- [nio-9901-exec-3] c.j.s.aop.RequestAopInterceptor : doRound after
2017-03-19 20:25:44.074 INFO 502 --- [nio-9901-exec-3] c.j.s.aop.RequestAopInterceptor : requestMapping is over
2017-03-19 20:25:44.074 INFO 502 --- [nio-9901-exec-3] c.j.s.aop.RequestAopInterceptor : doAfterReturing-->请求返回的信息为: hello world
```

作者:南柯问天 出处:http://www.cnblogs.com/question-sky/ 本文版权归本人和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/question-sky/p/6582105.html