1.什么是Spring框架的AOP?
我个人学习这些概念的话,一般都会把它的全部英文字母单词查出来,这样可以记得牢一点。
AOP:其实就是 Aspec Oriented Program,翻译成中文就是面向切面编程,或者面向方面编程。
一开始我也是有点懵的,什么是面向切面,我们不是一直都在用面向对象编程的吗?于是我就想面向切面的编程有什么好处?我就一定要用,学了之后才发现面向切面编程这方法很好,为什么说好呢?因为简单实用,而且对代码友好这是重点,它是采用非侵入式的方式设计的,就是这点就值得我用心去学了。下面用图来说明一下:
如果要在spring中明白怎么才能很好的使用,我觉得记关键字的方法挺好的,所以我们要理解这几个关键字
1.1Advice(通知)
其实理解起来也不难,所谓的通知,不就是有东西要告诉别人吗?其实在spring里面这也是一样的道理,其实就是声明什么时候执行你定义好的切面。
2.2JoinPoint
顾名思义,连接点,就是触发执行切面的点,比如当方法被调用,异常抛出。
3.3PointCut
其实就是定义你定义的切面里面要执行的内容,你定义好的方法或者类。
4.4Aspect
就是:Advice+PointCut 执行时间+执行的内容
5.5Introduction
其实就是说我们不仅仅可以插入新的类和方法,我们还能改变现有的类的成员属性和方法。
6.6Target
就是通知的对象,比如说通知就是你的管家,而你就是这个target对象,比如某天说:少爷,改吃药了。其实就是这个意思。
7.7proxy
这个我还不太了解,以后再说,任性!
8.8Weaving
就是切面植入的过程。
下面我们通过一个例子来说明吧,常用的用Aspectj的方法,听说EL表达式也行,但我不熟悉。
第一步:毫无疑问要创建spring工程了
第二步:定义执行的逻辑
首先本来要执行的方法
package com.annotation.action;
public class mainMethod {
public void printf(){
System.out.println("main method");
}
}
然后是要执行的切面的方法:
package com.annotation.action;
public class AdvisorMethod {
public void beforeRunning(){
System.out.println("mainMethod--------beforeRunning");
}
public void afterRunning(){
System.out.println("mainMethod--------afterRunning");
}
public void roundMethod(){
System.out.println("mainMethod------------roundMethod");
}
}
第三步:修改applicationContext.xml文件,用AspectJ的方法
<?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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 开启AspectJ代理切面 -->
<aop:aspectj-autoproxy/>
<bean id="AdvisorMethod" class="com.annotation.action.AdvisorMethod" ></bean>
<bean id="mainMethod" class="com.annotation.action.mainMethod"></bean>
</beans>
第四步:定义一个切面
<!-- 定义一个我们的切面 -->
<aop:config>
<aop:aspect ref="AdvisorMethod">
<aop:pointcut expression="execution(* com.annotation.action.mainMethod.*(..))" id="pointcut"/>
<aop:before method="beforeRunning" pointcut-ref="pointcut"/>
<aop:after method="afterRunning" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
第五步:查看结果
package com.annotation.action;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class mainMethodTest {
@Test
public void testPrintf() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
mainMethod m = (mainMethod) ctx.getBean("mainMethod");
m.printf();
}
}
结果:
是不是没有破坏原来代码的结构,是不是感到很爽啊。哈哈
2.使用AspectJ注解的方式
总是使用配置文件是不是觉得不够简洁,比较不好啊,我反正是这样觉得,不便于开发。
其实使用注解也不难,在上面的基础来我们来应用一下:
1applicationContext.xml文件不要更改,把定义的切面的部分删除(下面这一部分)
<!-- 定义一个我们的切面 -->
<aop:config>
<aop:aspect ref="AdvisorMethod">
<aop:pointcut expression="execution(* com.annotation.action.mainMethod.*(..))" id="pointcut"/>
<aop:before method="beforeRunning" pointcut-ref="pointcut"/>
<aop:after method="afterRunning" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
然后我们转到我们要执行的切面类里面
在这里要格外的注意,使用注解首先要创建一个空的方法public void method(){},名字随便取,但是这一步一定要。
package com.annotation.action;
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 AdvisorMethod {
//要执行切面方法的类的方法(地点),创建一个代理类
@Pointcut("execution(* com.annotation.action.mainMethod.*(..))")
public void method(){}
//在方法执行前
@Before("method()")
public void beforeRunning(){
System.out.println("mainMethod--------beforeRunning");
}
//方法执行后
@After("method()")
public void afterRunning(){
System.out.println("mainMethod--------afterRunning");
}
public void roundMethod(){
System.out.println("mainMethod------------roundMethod");
}
}
其他的不变。你会发现得到的结果是一样的。其他的方法自己测试一下。