AOP(Aspect-Oriented Programming -面向切面编程)其实是OOP(Object-Oriented Programing -面向对象编程) 思想的补充和完善。 我们知道,面向对象的特性是:“多态”,“继承” ,“封装”,对事物进行了抽象和封装,以此建立了一种对象的层次结构,它强调一种完整的自上而下的关系。不过 OOP 的设计允许开发者定义事务的纵向关系,并不适合定义横向关系,比如在记录日志的功能,安全性,异常处理和透明的持续性也都是如此,我们将这种散布在周围无关的代码称之为 横切,也即是 面向切面 编程AOP(Aspect Oriented Programming)。 一、 AOP的基本概念 aspect(切面): 通常是以类的形式出现 ,在此切面中定义 切入点和通知 join point(连接点): 是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。 point cut(切入点): 本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。 advice(通知增强): 是point cut的执行代码,是执行“方面”的具体逻辑。
要想更清楚的了解AOP的运行过程,就必须知道在java中 ,反射 的原理 ,springAOP 也是利用了反射的原理来对类进行操作。 在 spring 中,配置AOP的方式有两种,一种是在XML中配置,另一种是使用注解的方式配置。 1.在XMl配置 我定义的xml文件名为 MyContext.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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" > <!-- 使用注解驱动 --> <mvc:annotation-driven /> <!-- 开启包扫描 --> <context:component-scan base-package="com.spring.advice"/> <!-- 开启代理模式 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <bean id="logAdvice" class="com.spring.advice.LogAdvice"></bean> <bean id="userDao" class="com.spring.dao.UserDao"></bean> <aop:config> <aop:aspect ref="logAdvice"> <aop:before method="log" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> <aop:around method="around" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> <aop:after method="after" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> </aop:aspect> </aop:config> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 aop:aspect 表示的是切面,通常是一个类 ,ref 链接到 初始化的bean中 ,也就是<bean id="logAdvice" class="com.spring.advice.LogAdvice"></bean> aop:before 表示执行方法 之前 method 指的是对应的方法名 ,pointcut 表示切入点, target(目标类路径),execution(* update(…)); 第一个*号表示通配符 表明返回任意类型 ,update 表示执行的 目标函数名 , (…) 指的是 传递的参数个数,这里不限制,抽象了,一般来说都要写具体,比如(int ,string) <aop:around method="around" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> <aop:after method="after" pointcut="target(com.spring.dao.UserDao) and execution(* update(..))"/> aop:around 和 aop:after 分别表示 周围 和之后,具体的实现跟 aop:aspect 一样。 2.使用注解的方式配置 在spring中,已经为我们定义好了 AOP的注解( @Aspect, @Component :需要在通知(增强)类中使用 @Before :在被代理对象的方法前先调用 (前置通知) @After :在被代理对象的方法调用后再执行(后置通知) @Around :将被代理对象的方法封装起来,用环绕通知取代) @AfterReturning 在被代理对象的方法正常返回后调用要求,被代理对象的方法在执行过程中没有出现异常 @AfterThrowing 在被代理对象的方法抛出异常后调用要求,被代理对象的方法在执行过程中出现异常 我们只需要在类和方法名前加上注解就好了,具体代码如下: LogAdvice.java
@Component @Aspect public class LogAdvice { // 表示记录 UserDao 下的所有方法 都执行 @Before("execution(* com.spring.advice.UserDao.*(..))") public void log(JoinPoint jp) { System.out.println(new Date() +"更新日志"); } //@Around 利用的java的反射原理机制执行 pjp.proceed(); 方法 @Around("execution(* com.spring.advice.UserDao.insert(int,String))") public Object around(ProceedingJoinPoint pjp) throws Throwable { Object result =null; result = pjp.proceed(); return result; } @After("execution(* com.spring.advice.UserDao.*(..))") public void after() { System.out.println(new Date() +"更新完毕"); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 UserDao.java
@Component public class UserDao { public void insert(int n , String password) { System.out.println("插入数据(int,String)"+ n +" , "+password); } } 1 2 3 4 5 6 Test.java
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("MyContext.xml"); UserDao ud = (UserDao) ctx.getBean("userDao"); ud.insert(1, "10086"); } } 1 2 3 4 5 6 7 8 结果:
这就是所谓的面向切面编程,它不破坏方法的完整性,有兴趣的小伙伴可以去研究一下设计模式中的代理模式,相信会使你对AOP的机制更加的了解。 --------------------- 作者:王码农 来源:CSDN 原文:https://blog.csdn.net/qq_41993438/article/details/84483560 版权声明:本文为博主原创文章,转载请附上博文链接!
|