AOP介绍【原创】
AOP就是面向切面编程(Aspect-Oriented Programming),这是一个相对来说较新的概念,一般来说我们设计一个项目,都会按照分模块来设计,例如,下面是一个模块设计图:
我们可以看到将微博系统分为了4个模块,这是我们常用的方法,但是,我们可能会有一个需求,那么就是每个操作都需要进行日志记录,例如注册的时候需要日志纪录,登陆的时候需要纪录,发微薄和查看微博都需要纪录。
我们可能第一个想法就是 在每个操作处都增加一个日志纪录的语句,这样的话我们每个操作都能在日志中纪录下来,这可能是个解决方案,但是这个方法略显麻烦,我们有几个模块就需要在几个地方加上日志操作的模块,如果日志的配置有什么改变,那么我们就需要在多处进行修改了。
出于诸多考虑,我们就寻求更好的解决方法,于是就有人提出了AOP的概念,这里我们对以上的模块图进行修改,得到如下的图:
我们可以发现这里有个切面横跨所有的模块,这就是AOP的思想,我们不在每个模块上使用日志纪录了,而是交给Spring来完成。
下面,我就AOP的思想给大家演示一下实例:
这里举一个例子,这里引入一个人物- 小明,小明不会游泳,但是可能海贼王看多了,所以对大海有莫名的喜欢,但是可怜天下父母心,小明妈妈肯定会拦着小明不让他去海边游泳的,因此,就有了下面这个案例,首先来个传统版本的:
package info.liuliqiang.simple;
public class Swimmer
{
public void swim(String name)
{
System.out.printf(%s说:"誰也不能阻挡我征服大海."n, name);
if(name.equals(小明))
{
System.out.println(小明被妈妈发现去游泳,一顿狠揍...);
}
}
}
//Main.java
package info.liuliqiang.main;
import info.liuliqiang.simple.Swimmer;
public class Main
{
public static void main(String[] args)
{
new Swimmer().swim(张三);
new Swimmer().swim(李四);
new Swimmer().swim(小明);
}
}
这里很明确,就是如果小明去游泳被他妈妈发现的话就是一顿揍,这里小明妈妈要发现小明是不是去游泳了就需要在swim函数中判断,也就是说需要亲自到海边去看游泳的人里面有没有小明。
这里是不是就显得麻烦了,所以下面给出一个AOP风格的版本,因为要使用Spring的东西,所以有几个jar包可能你是需要的(可以点击下载),代码如下:
//Swimmer.java
package info.liuliqiang.aop;
public class Swimmer
{
public void swim(String name)
{
System.out.printf(%s说:"誰也不能阻挡我征服大海."n, name);
}
}
//SwimmerFinder.java<
package info.liuliqiang.aop;
import org.aspectj.lang.JoinPoint;
public class SwimmerFinder
{
public void someoneSwim(JoinPoint joinPoint)
{
String swimmerName = (String) joinPoint.getArgs()[0];
if(swimmerName.equals(小明))
{
System.out.println(小明被妈妈发现去游泳,一顿狠揍...);
}
}
}
//Main.java
package info.liuliqiang.main;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import info.liuliqiang.aop.Swimmer;
public class Main
{
public static void main(String[] args)
{
BeanFactory bf = new ClassPathXmlApplicationContext(config.xml);
Swimmer swimmer = (Swimmer) bf.getBean(swimmer);
swimmer.swim(张三);
swimmer.swim(小明);
swimmer.swim(李四);
}
}
//config.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:tx=http://www.springframework.org/schema/tx
xsi:schemaLocation=http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd>
<!-- 启用AspectJ对Annotation的支持 -->
<aop:aspectj-autoproxy/>
<bean id=swimmer class=com.liuliqiang.aop.Swimmer/>
<bean id=swimmerFinder class=com.liuliqiang.aop.SwimmerFinder/>
<aop:config>
<aop:aspect id=swimmerAspect ref=swimmerFinder>
<aop:pointcut expression=execution(* swim*(..)) id=swim/>
<aop:after method=someoneSwim pointcut-ref=swim/>
</aop:aspect>
</aop:config>
</beans>
好的,以上就是一个简单的AOP例子,这里我们需要解释一下,这里小明的妈妈不再自己去海边看小明是不是在游泳了,而是有人在海边看着,如果有人游泳就告诉小明妈妈,然后小明妈妈发现是小明的话那么就找棍子去了。。。
关于AOP,这里有几个概念需要解释一下:
- Join Point(连接点):程序运行时的某个阶段点,如某个方法调用、异常抛出,也是Advice注入的位置
- Pointcut(切入点):是Join Point的集合,他是程序中需要注入Advice的位置的集合,指明Advice在什么样的条件下才能被触发。
- Advice(通知):是某个连接点所采用的处理逻辑,也就是向连接点注入的代码。
- Advisor:是Pointcut和Advice的配置器,它包括Pointcut和Advice,是将Advice注入程序中Pointcut位置的代码。
光说概念可能大家没感觉,还是拿小明的例子来说,游泳就是一个Join Point,因为这个就是需要处理的调用点,然后这里面暂时没有Pointcut,如果硬要所有的话那么也是游泳,因为这里只监控了一个Join Point,所以说有没有都可以。然后小明被妈妈怒揍这是一个Advice,也就是说对游泳的处理逻辑,最后Advisor就是我们的配置文件config.xml了,其实也是Spring的AOP容器。
嗯,以上就是一个简单的AOP介绍了,希望对大家能够有所帮助,有所触动。