版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38111957/article/details/83715587
一、引言
什么是前置通知和后置通知?
前置通知:调用方法之前,后置通知:调用方法之后。
那比如之前实现的日志记录功能,都是在调用方法之前记录的日志,AOP可以很灵活的控制,切点在什么时候执行。
二、功能需求
还是拿我们之前代理那一章节中的例子。有一个针对用户的增删改查的方法,需要做日志记录。
public interface UserMange {
void insertUser(String username, String password);
String findUser(Integer id);
void deleteUser(Integer id);
void update(String username, String password, Integer id);
}
import org.springframework.stereotype.Service;
@Service
public class UserMangeImpl implements UserMange {
public void insertUser(String username, String password) {
System.out.println("----------UserMangeImpl.insertUser-----------");
}
public String findUser(Integer id) {
System.out.println("----------UserMangeImpl.findUser-----------");
return "张山";
}
public void deleteUser(Integer id) {
System.out.println("----------UserMangeImpl.deleteUser-----------");
}
public void update(String username, String password, Integer id) {
System.out.println("----------UserMangeImpl.update-----------");
}
}
三、使用AOP实现
首先我们先来学习一个采用注解的方式来实现,AspectJ,java社区里面最完整,最流行的AOP框架。
在Spring2.0以上的版本,可以使用基于AspectJ注解或XML配置的AOP。
先引入AspectJ jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.0</version>
</dependency>
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 定义一个切点
*/
@Aspect
public class InsertLogHeadr {
/**
* 定一个Pointcut,此方法没有返回值和参数
* 该方法就是一个标识,不进行调用
*
* execution中解释:
* 第一个* :表示任意修饰符的方法
* com.spring.two.UserMangeImpl.* : 具体的类下面全部的方法
* (..):任意参数列表
*/
@Pointcut("execution(* com.spring.two.UserMangeImpl.*(..))")
public void beforLog(){}
/**
* 定义Advice,表示应用到那些Pointcut订阅的Joinpoint上
* Before 调用方法之前
*/
@Before("beforLog()")
public void insertLogBefor(){
System.out.println("InsertLogHeadr.insertLogBefor");
}
/**
* 定义Advice,表示应用到那些Pointcut订阅的Joinpoint上
* After 调用方法之后
*/
@After("beforLog()")
public void insertLogAfter(){
System.out.println("InsertLogHeadr.insertLogBefor");
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!--扫描注解的包-->
<context:component-scan base-package="com.spring.two"></context:component-scan>
<!--开启对AspectJ注解对支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!--需要定义的切点配置到IOC容器当中-->
<bean id="InsertLogHeadr" class="com.spring.two.InsertLogHeadr"></bean>
</beans>
最后测试咯:不管调用UserMange中任意一个方法, 都会执行切点中定义的方法。
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext-two.xml");
UserMange userMange = (UserMange)beanFactory.getBean("userMangeImpl");
userMange.findUser(1);
}
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
InsertLogHeadr.insertLogBefor
----------UserMangeImpl.findUser-----------
InsertLogHeadr.insertLogAfter
Process finished with exit code 0