概念
aop(Aspect Oriented Programming)面向切面编程,那么面向切面是什么意思呢?第一次接触的时候看着spring大学教程写了一大串文字描述反复用心读了几遍还是似懂非懂,很无奈,为啥书写的那么晦涩,其实本人特别不理解一些概念为啥搞的这么复杂,后来懂了其实并没有那么复杂,严重影响对技术的掌握,还有对简写也比较反感有些简写用的时间太长都很难百度到它的全称,对新学习的人来说特别不方便。
面向切面编程其实让一些代码产生了新的联系,联系的产生是因为大家都有了一块共同的代码块。共同代码块和联系让我们联想到oop(Object Oriented Programming)面向对象编程,他们的联系产生是因为继承(实现)了父类的代码(子类的共同代码),画个图很容易理解父子的关系是纵向的,有纵便有横,那么aop就是解决横向关系。
横和纵其实放在自然世界来都特别容易立即。纵可以用车来理解,自行车、摩托车、汽车都属于车,核心部件(功能)都相同。那么横向关系可以理解朋友关系,你和朋友产生关系是因为某些共同的爱好、利益等,但是这些关系不是你的核心,天下没有不散的宴席,没有那些朋友我们还会结交其他朋友。
其实本质都是代码复用,但是oop的代码复用是核心代码的复用,“关系”比较“铁”,耦合度比较高。aop复用的代码不是核心代码耦合度应该比较低,也有便于维护的好处。一般切入的功能如权限、日志、事务等。这样就将核心和非核心分开了,这样的系统设计也是比较合理的。
然后aop的本质是代理可以参考: java的静态代理和动态代理
aop的基本实现
pom依赖jar引入
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.6</version>
</dependency>
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 被代理对象 -->
<bean id="math" class="test.Math"></bean>
<!-- 切入操作 -->
<bean id="advices" class="test.Advices"></bean>
<!-- 动态生成代理aop配置 -->
<aop:config proxy-target-class="true">
<!-- 切面 -->
<aop:aspect ref="advices">
<aop:pointcut id="pointcut" expression="execution(* test.Math.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
package test;
/**
* 被代理的目标类
*/
public class Math{
//加
public int add(int n1,int n2){
int result=n1+n2;
System.out.println(n1+"+"+n2+"="+result);
return result;
}
//减
public int sub(int n1,int n2){
int result=n1-n2;
System.out.println(n1+"-"+n2+"="+result);
return result;
}
//乘
public int mut(int n1,int n2){
int result=n1*n2;
System.out.println(n1+"X"+n2+"="+result);
return result;
}
//除
public int div(int n1,int n2){
int result=n1/n2;
System.out.println(n1+"/"+n2+"="+result);
return result;
}
}
package test;
import org.aspectj.lang.JoinPoint;
/**
* 通知类,横切逻辑
*
*/
public class Advices {
public void before(JoinPoint jp){
System.out.println("----------前置通知----------");
System.out.println(jp.getSignature().getName());
}
public void after(JoinPoint jp){
System.out.println("----------最终通知----------");
}
}
允行结果
----------前置通知----------
add
10+5=15
----------最终通知----------
----------前置通知----------
div
10/5=2
----------最终通知----------
----------前置通知----------
mut
10X5=50
----------最终通知----------
----------前置通知----------
sub
10-5=5
----------最终通知----------
aop的注解实现
上面的pom文件、class Math不变
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 被代理对象 -->
<bean id="math" class="test.Math"></bean>
<!-- 切入操作 -->
<bean id="advices" class="test.Advices"></bean>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
Advices 使用注解
package test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
* 通知类,横切逻辑
*
*/
@Aspect
public class Advices {
@Before("execution(* test.Math.*(..))")
public void before(JoinPoint jp){
System.out.println("----------前置通知----------");
System.out.println(jp.getSignature().getName());
}
@After("execution(* test.Math.*(..))")
public void after(JoinPoint jp){
System.out.println("----------最终通知----------");
}
}
运行结果还是一样