面向切面编程(AOP)

谈到面向切面编程,就难免提到面向对象编程(OOP)

两者反映两种不同的设计思想,OOP将某一类实体及其属性和行为进行抽象和封装,通过类的实例化、对象之间的调用来组成完整程序。
而AOP中所谓的“切面”指的是业务处理过程中某个步骤或阶段,AOP是对这些步骤进行处理,以降低各个步骤间的耦合度。
简而言之,OOP是将现实存在的对象进行封装,例如对于“学生”这类对象,可以建立“Student”类,并将“上课”、“学习”等行为,以及“班级”、“学号”等属性封装在里面。
但这时还会有重复的情况,比如学生和教师查询学生成绩这个行为之后,都要记录一条日志,那么就在两个类中出现了同样的代码,即使将代码封装在一个类中,也需要分别调用这个类。这时就需要AOP了。AOP可以将记录日志的行为(不同类共有的代码)写在切片里,再在查询成绩的方法处设一个标记(切面),一运行到这里,就自动执行对应切片里的代码。
这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

知乎上的解释更简洁些:https://www.zhihu.com/question/24863332

AOP中的基本概念
1.Target object   
  AOP关注的业务部分。
2.Pointcut     
  AOP找到Target object后,准备在该对象的指定方法上执行Advice代码,而这个指定方法就是Pointcut。
3.Advice      
  在切点上真正执行的代码,写在一个java文件里。
4.join point    
  负责将Advice和Pointcut编织到一起(建立对应关系,使程序知Advice切入到哪里)
5.Aspect
  将pointcut、advice和joinpoint模块化,即共有功能的实现。

AOP需要的包:spring-aop-x.x.x.RELEASE.jar
       aspectjweaver-x.x.x.jar
(待确认)
       

使用方法:

需要的文件:
  .xml配置文件
  Target object文件
  Advice文件

Target object文件(HelloService)内容如下:

package AOP_Demo;

public class HelloService
{
    <!--一个普通方法-->
    public void say()
    {
        System.out.println("eat");
    }
}

Advice文件(MyAdv)内容如下:

package AOP_Demo;
import org.aopalliance.aop.Advice;

public class MyAdv implements Advice
{
    <!--插入到pointcut的方法-->
    public void beforeAdvice()
    {
        System.out.println("前置通知");
    }
}

配置文件(app.xml)内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!--文件头需要增加一些内容-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--指定target object文件,根据情况改变-->
    <bean id="target" class="AOP_Demo.HelloService"/>
    <!--指定Advice文件,根据情况改变-->
    <bean id="adv" class="AOP_Demo.MyAdv"/>
    <!--Spring AOP的配置-->
    <aop:config>
    <!--Aspect-->
        <aop:aspect ref="adv" id="asp">
            <!--注意:可以使用通配符寻找pointcut,
                 一个*表示任意长度字符
                 两个.表示该包下的任意子包名
                 例:execution(* com.demo..*.*(..)
            其中:第一个*表示当前方法对应的任意类型
                 后面的一串:表示demo包下任意子包下任意类的任意方法,
                 小括号中的..表示方法中的任意个数、类型的参数
              -->
              <!--定义pointcut,可见指向了Target object中的.say()方法-->
            <aop:pointcut expression="execution(void AOP_Demo.HelloService.say())" id="pc"/>
            <!--定义织入的方式(before)、方法(beforeAdvice)和pointcut(pc),即“在运行pointcut指定的方法之前执行Advice中的beforeAdvice方法”
            Advice文件位置是在<aop:aspect>中通过ref定义的-->
            <aop:before method="beforeAdvice" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>

</beans>

下面写一个带主方法的文件,来运行一下:

package AOP_Demo;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopTest
{
    public static void main(String args[])
    {
        ApplicationContext c;
        c = new ClassPathXmlApplicationContext("app.xml");
        HelloService h = (HelloService) c.getBean("target");
        h.say();
    }
}

结果如下:

前置通知
eat

可见,执行Target object的.say()方法之前,自动执行了Advice中的指定方法。

(待完善)
(萌新一枚,难免有错误或疏漏,欢迎指正)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值