什么是面向切面编程(AOP) ?
首先我们谈谈传统中的oop 面向对象编程,我们不需要关注具体是”怎么做,怎么实现“,我们只需要知道“谁去做”,我们把关注点放在对象上面,而不是实现的细节当中。而AOP可以理解成OOP的一种延续补充,因为OOP可以使代码复用性更高,逻辑更加清晰,但是在某些业务中,OOP并不是万能的。常用的场景 日志 权限。
比如 现在我们需要在业务层的所有方法去记录一些日志信息,如果我们使用OOP的思想,那么就需要在每个类中去写着个日志方法,这样的话代码太沉重了,当然你也可以去封装这个方法 然后再去每个类中去调用,但是这样会导致耦合太高,为了解决这种问题,我们提出了AOP 这种思想,我们把日志方法封装起来,然后进行一下简单的配置,利用Java的反射让他程序运行时动态的将我们的代码插入到我们需要的位置。一般情况下日志都是通过代理模式进行实现 不知道代理模式的可以去看下我的专栏中的设计模式,这里我就不在去解释了。
首先介绍一下AOP中的一些术语:
连接点(Joinpoint):我们在什么地方去切入或者说在什么地方去执行我们代码(spring只支持在方法的切入)
切入点(Pointcut):相当于一个连接点的集合,通过正则表达式去匹配我们需要的类或者方法名称指定切入点
通知(Advice):定义了切面是什么时候以及何时使用,除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,他应该 应用在某个方法被调用之前?之后?之前之后都调用,还是在方法抛出异常时调用。
切面(Aspect) :是切入点和通知的结合,通知和切点共同定义了切面的内容,他是什么,在何时何处完成其功能。
织入(weave):织入是把切面,应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:编译期,类加载时,运行期
Spring提供了4种类型的AOP支持:
1.基于代理的经典 Spring-AOP
2.纯POJO切面
3.@ Aspectj注解驱动
4.注入式Aspectj切面
这里我使用注解的方式来写一个案例
1.先创建在spring的xml中开启AOP
<!-- 需要在ioc容器开启基于注解的AOP功能 -->
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.fcwily.*"/>
2.创建切面类
@Aspect
@Component
public class TestAspect {
//表达式:[方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数)
@Before("execution(* com.fcwily.aop.proxy.*.*(..))")
public void s() {
System.out.println("前置通知");
}
@AfterReturning("execution(* com.fcwily.aop.proxy.*.*(..))")
public void s2() {
System.out.println("返回通知");
}
@AfterThrowing("execution(* com.fcwily.aop.proxy.*.*(..))")
public void s3() {
System.out.println("异常通知");
}
@After("execution(* com.fcwily.aop.proxy.*.*(..))")
public void s4() {
System.out.println("最终通知");
}
}
3.创建一个业务类
@Component
public class TestService {
public void talkHello() {
System.out.println("hello world");
}
}
4.测试类
public class TestMain {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("beans.xml");
TestService tService=applicationContext.getBean(TestService.class);
tService.talkHello();
}
}
打印结果:
前置通知
hello world
最终通知
返回通知