昨天我们对Spring Aop的概念有了一个清晰的认识,今天我看了很多网上很多人的博客,写了一个Spring Aop的小练习,以此来加深对Aop的印象和理解。
使用的工具是Idea ,用Maven 建了一个Maven工程,其中引入了Spring 和 SpringMVC 和 AOP,使用注解的方式来实现了一个AOP的小练习,并在这里做了一个整理和记录,方便以后查看。
首先,使用Maven 新建一个Maven 项目,并且引入对 Spring MVC的依赖,这一点不会的同学可以去我的博客去看另一篇:
https://blog.csdn.net/liuying1802028915/article/details/90643364
我的项目结构是这样的:
这是最终的项目结构
我们先实现不使用AOP的功能。
很简单就是一个Controller,一个Service
对了首先现在pom文件中引入我们想要的jar包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
接下来我帖上Controller和Service
HelloController
package com.taoj.controller;
import com.taoj.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@Autowired
private DemoService demoService;
@RequestMapping("hello")
@ResponseBody
public String sayHello(){
demoService.doSome1();
demoService.doSome2();
demoService.doSome3();
System.out.println(demoService.doSome4("小虎", 24));
return "helo dddd";
}
}
DemoService
package com.taoj.service;
public interface DemoService {
public void doSome1();
public void doSome2();
public void doSome3();
public String doSome4(String name, int age);
}
DemoServiceImpl
package com.taoj.service.impl;
import com.taoj.service.DemoService;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
@Service
@EnableAspectJAutoProxy
public class DemoServiceImpl implements DemoService {
@Override
public void doSome1() {
System.out.println("DemoServiceImpl---doSome1");
}
@Override
public void doSome2() {
System.out.println("DemoServiceImpl---doSome2");
}
@Override
public void doSome3() {
System.out.println("DemoServiceImpl---doSome3");
}
@Override
public String doSome4(String name, int age) {
String msg = name+"今年"+age+"岁了";
System.out.println("msg:"+msg);
return msg;
}
}
接下来我们在配置文件DispatcherService.xml中添加 注解扫描的代码:
<!--添加扫描-->
<context:component-scan base-package="com.taoj" />
我认为以上已经是添加完Tomcat了,然后启动tomcat, 访问:http://localhost:8080/aop/hello.form
界面展示如下:
没问题
后台Console输出为:
DemoServiceImpl---doSome1
DemoServiceImpl---doSome2
DemoServiceImpl---doSome3
msg:小虎今年24岁了
小虎今年24岁了
可以依次理解其中的含义,以上都是SpringMVC的知识,不理解的可以去看SpringMVC相关的知识。
接下来AOP登场了,我定义了一个切面类LogAspect.java
package com.taoj.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(public void com.taoj.service.impl.DemoServiceImpl.doSome2())")
public void pointCut(){
}
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
String functionName = joinPoint.getSignature().getName();
System.out.println(functionName+"运行了,参数列表是"+args);
}
}
输出结果为:
DemoServiceImpl---doSome1
doSome2运行了,参数列表是[Ljava.lang.Object;@121cfd0
DemoServiceImpl---doSome2
DemoServiceImpl---doSome3
msg:小虎今年24岁了
小虎今年24岁了
我们看到引入切面类之后多了这句:
doSome2运行了,参数列表是[Ljava.lang.Object;@121cfd0
接下来我们来分析一下LogAspect,我们认为 LogAspect.java为一个切面类(这样理解应该对吧,如果有不对之处,还请指正)
首先LogAspect 类 头上引入了@Aspect注解,说明这是一个切面类,@Component 是为了Spring 把这个类扫描进去
@pointCut 后面的是切点表达式 :
execution(public void com.taoj.service.impl.DemoServiceImpl.doSome2() 这个为切点表达式,这一看一目了然,只针对
com.taoj.service.impl.DemoServiceImpl 类中的 doSome() 方法
然后后面的
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
String functionName = joinPoint.getSignature().getName();
System.out.println(functionName+"运行了,参数列表是"+args);
}
这个方法表示在在切点(满足切点表达式的方法)方法执行前执行,所以我们再来看输出结果:
DemoServiceImpl---doSome1
doSome2运行了,参数列表是[Ljava.lang.Object;@121cfd0
DemoServiceImpl---doSome2
DemoServiceImpl---doSome3
msg:小虎今年24岁了
小虎今年24岁了
我们看到 doSome2运行了,参数列表是[Ljava.lang.Object;@121cfd0 是在 DemoServiceImpl---doSome2 之前执行
这样就能说明结果了。
接下来再来看:LogAspect.java
package com.taoj.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(public void com.taoj.service.impl.DemoServiceImpl.doSome2())")
public void pointCut(){
}
// @Before("pointCut()")
// public void logStart(JoinPoint joinPoint){
// Object[] args = joinPoint.getArgs();
// String functionName = joinPoint.getSignature().getName();
// System.out.println(functionName+"运行了,参数列表是"+args);
// }
@Before("pointCut()")
public void logStart(){
System.out.println("LogAspect----logStart");
}
@AfterReturning("execution(public String com.taoj.service.impl.DemoServiceImpl.*(..))")
public void afterReturning(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("LogAspect---afterReturning--返回结果前,该方法名为"+methodName+",方法参数为"+args);
}
@After("execution(* com.taoj.service.impl.DemoServiceImpl.*())")
public void logEnd(){
System.out.println("LogAspect---logEnd");
}
}
输出结果为:
DemoServiceImpl---doSome1
LogAspect---logEnd
LogAspect----logStart
DemoServiceImpl---doSome2
LogAspect---logEnd
DemoServiceImpl---doSome3
LogAspect---logEnd
msg:小虎今年24岁了
LogAspect---afterReturning--返回结果前,该方法名为doSome4,方法参数为[Ljava.lang.Object;@e971b3b
小虎今年24岁了
以上结果我们可以通过分析切点表达式来分析得到,很简单,我这里就不再赘述 (*的使用,还可以用within,this等)以后再学习
以上这就是一个简单的aop的实现。方便以后查看
不积跬步,无以至千里
不积小流,无以成江海