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,因为这个就是需要处理的调用点,然后这里面暂时没有Pointcut,如果硬要所有的话那么也是游泳,因为这里只监控了一个Join Point,所以说有没有都可以。然后小明被妈妈怒揍这是一个Advice,也就是说对游泳的处理逻辑,最后Advisor就是我们的配置文件config.xml了,其实也是Spring的AOP容器。

嗯,以上就是一个简单的AOP介绍了,希望对大家能够有所帮助,有所触动。