SpringAOP练习笔记
相关名词
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志,俺去那,缓存,事务等等。
- 切面(Aspect):横切关注点被模块化的特殊对象,即,它是一个类。
- 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知后创建的对象。
- 切入点(PointCut):切面通知执行的“地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
以上涉及了很多个名词,很容易令我们混乱。本次练习我们着重关注切面、通知、切入点三个部分。
前期准备工作
本次练习是在SpringBoot的基础上进行练习。
- 新建一个SpringBoot项目,只导入web相关依赖。因为要使用到Aop,因此还需要在pom.xml文件中添加上Aspect依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
-
进行对象创建
UserDAO:
public interface UserDao { void add(); void delete(); void update(); }
UserDaoImpl:
public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("调用了增加的方法!"); } @Override public void delete() { System.out.println("调用了删除的方法!"); } @Override public void update() { System.out.println("调用了更新的方法!"); } }
UserService:
public interface UserService { void add(); void delete(); void update(); }
UserServiceImpl:
public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void add() { userDao.add(); } @Override public void delete() { userDao.delete(); } @Override public void update() { userDao.update(); } }
User:
public class User { private String neme; public String getNeme() { return neme; } public void setNeme(String neme) { this.neme = neme; } }
因此本次练习是基于SpringBoot实现的,但在测试中我们并不会读取SpringBoot的配置文件,而是使用我们自己创建的配置文件
创建配置文件
beans.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: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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解装配-->
<context:annotation-config/>
<bean id="userService" class="com.kuang.service.UserServiceImpl"/>
<bean id="userDao" class="com.kuang.dao.UserDaoImpl"/>
</beans>
在配置文件中将刚刚创建的对象都注册到Spring中。
测试类:
@SpringBootTest
public class Test {
@org.junit.jupiter.api.Test
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.delete();
}
}
特别注意:我们需要读取自己创建的配置文件,并且所有的对象都不要自己new,要通过Spring去获取bean的方式去获取。
开始测试
方式一 通过API实现
-
创建通知类 ,通知类需要实现通知类型方法
前置通知:
public class Log implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName() + "执行了" + method.getName() + "方法!"); } }
后置通知:
public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("执行了" + method.getName() + "方法!"); } }
-
在配置文件中进行配置。
<bean id="log" class="com.kuang.log.Log"/> <bean id="afterLog" class="com.kuang.log.AfterLog"/> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config>
至此,Aop功能已经可以实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5dtZpuA-1607567574295)(C:\Users\农昂\AppData\Roaming\Typora\typora-user-images\image-20201210095451049.png)]
方式二 配置切面实现
- 创建切面类并注册到spring中:
public class DiyPointCut {
public void before(){
System.out.println("=========方法执行前=========");
}
public void after(){
System.out.println("========方法执行后===========");
}
}
-
修改配置文件
<bean id="diyPoincCut" class="com.kuang.diy.DiyPointCut"/> <aop:config> <aop:aspect ref="diyPoincCut"> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
即可实现AOP。
方式三 使用注解实现
-
创建切面
@Aspect public class AnnotationPointcut { @Before("execution(* com..kuang.service.UserServiceImpl.*(..))") public void before(){ System.out.println("方法执行前==========="); } }
-
修改配置文件
<bean id="annotationPointcut" class="com.kuang.diy.AnnotationPointcut"/> <aop:aspectj-autoproxy/>
即可实现Aop。
System.out.println("方法执行前==========="); }
}
2. 修改配置文件 ```xml <bean id="annotationPointcut" class="com.kuang.diy.AnnotationPointcut"/> <aop:aspectj-autoproxy/>
即可实现Aop。
-