AOP简介
AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充。在运行时,动态的将代码切入到类的指定方法、指定位置上的编程思想。
优点:降低代码之间的耦合,提高代码的复用性。
spring底层采用了动态代理的方式实现aop。采用了两种代理:
JDK的动态代理:如果贝代理类实现了接口,默认jdk。(使用了反射,耦合度低)
CGLIB的动态代理:如果累没有实现接口,会使用CGLIB动态代理。(使用字节码处理器ASM,性能好)
AOP常用术语
1,目标对象(Target):指将要被增强的对象。
2,切面(Aspect):指非业务逻辑。
3,连接点(JoinPoint):业务接口中的方法,可以被切面织入的方法。
4,切入点(PointCut):指切面具体织入的方法。
5,通知(Advice):通知是切面的一种实现。
6,织入(Weaving):将切面代码插入到目标对象的过程。(invoke)
7,AOP代理(Aop proxy)
目前spring用得是AspectJ对AOP的实现
Spring 2.0引入了,下面是目前spring AOP的注解实现方式
创建一个Module aoptest
1,添加以下目录结构,添加xml配置文件
2,pom.xml文件加入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
3,添加以下目录结构
目标类的内容:
@Service("userService")
public class UserServiceIpml implements UserService {
@Override
public void addUser(){
System.out.println("执行addUser()方法");
}
@Override
public void deleteUser(){
System.out.println("执行deleteUser()方法");
}
@Override
public int updateUser(){
System.out.println("执行updateUser()方法");
return 1024;
}
@Override
public void selectUser(){
System.out.println("执行selectUser()方法");
}
@Override
public void selectUserById(int id ) throws Exception{
System.out.println("执行selectUserById()方法");
if(id==0){
throw new Exception();
}
}
}
切面内容:
@Aspect
@Component
public class MyAspect {
@Before("execution(* *..UserServiceIpml.addUser())")
public void before(){
System.out.println("==============前置通知==============");
}
@After("execution(* *..UserServiceIpml.selectUser())")
public void after(){
System.out.println("==============最终通知==============");
}
@AfterReturning(value="execution(* *..UserServiceIpml.updateUser())",returning="result")
public void afterReturning(int result){
System.out.println("==============后置通知=============="+result);
}
@AfterThrowing(value="execution(* *..UserServiceIpml.selectUserById(..))",throwing = "e")
public void afterThrowing(Exception e){
System.out.println("==============异常通知=============="+e);
}
@Around("execution(* *..UserServiceIpml.deleteUser())")
public Object around(ProceedingJoinPoint pjp)throws Throwable{
System.out.println("==============环绕通知:前==============");
Object proceed= pjp.proceed();
System.out.println("==============环绕通知:后==============");
return proceed;
}
}
配置文件XML内容:
<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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cn.test"/>
<aop:aspectj-autoproxy/>
</beans>
测试类:
public class test01 {
@Test
public void testAop(){
ApplicationContext context=new ClassPathXmlApplicationContext( "applicationContext.xml");
UserService service=(UserService) context.getBean("userService");
service.addUser();
service.selectUser();
service.deleteUser();
service.updateUser();
try {
service.deleteUser();
}catch (Exception e){
e.printStackTrace();
}
//关闭容器
//((ClassPathXmlApplicationContext)context).close();
}
}
解析:在切面和目标类加了注解,并在配置文件加入了扫描包的配置和开启动态代理的配置
注意:扫描包最好一开始就创建好,在各个pom.xml文件配好
动态代理:https://www.iteye.com/blog/chenjumin-2437690
springboot:https://www.cnblogs.com/onlymate/p/9630788.html