【AOP】

什么是AOP

AOP即面向切面编程
Aspect Oriented Program

什么是切面

假设我们需要在一个方法的开头和结尾进行日志的输出,通常的做法是直接在方法里写入日志输出的代码。
但如果我们需要对多个甚至n多个方法都实现日志输出,这太麻烦了,而且代码复用率不高。

那我们进行一个假设:

  • 有三个方法,每个方法的头尾都要输出日志。当然,一个个输出太麻烦了。
    在这里插入图片描述

  • 那么,假若我对这三个方法切一刀

  • 我们将得到三个统一的刀口,将三个刀口当作一整个切面

  • 接着,把这个切面抽象成一个可以进行编程的对象

  • 然后,我们对该对象写入所需要的功能,例如输出日志。

  • 至此——我们就完成了要求这三个方法的头尾都要输出日志的操作。

切一刀

这样我们就能对 AOP是什么 理解个大概了。
:通过上面的例子,由于我们把切面当作了一个对象,那么有对象就会有IOC,所以AOP是必定基于IOC的。

AOP和IOC/DI只是一种软件设计思想 ,不单是Java语言,其他语言都有这种设计思想概念

代码部分

AOP分为核心业务功能和辅助功能(aspect),两种功能可以分别独立。

  • 核心业务功能:
    比如登陆功能,即便是没有性能统计和日志输出,也可以正常运行。
  • 辅助功能(也叫切面aspect):
    打印日志。
    事务处理(commit,close)
    权限处理

上面的例子其实已经把AOP的概念讲出来了:能够选择性地,低耦合地将核心业务功能(三个方法)和辅助功能(输出日志)结合在一起的编程思想就叫做面向切面编程即AOP。

准备业务类 ProductService.java

package com.how2java.service;
 
public class ProductService {
     
    public void doSomeService(){
         
        System.out.println("doSomeService");
         
    }
     
}

准备日志切面 LoggerAspect.java

该日志切面的功能是 在调用核心功能之前和之后分别打印日志,切面就是原理图中讲的那些辅助功能。

package com.how2java.aspect; 
import org.aspectj.lang.ProceedingJoinPoint;   
public class LoggerAspect {
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("start log:" + joinPoint.getSignature().getName());
        Object object = joinPoint.proceed();
        System.out.println("end log:" + joinPoint.getSignature().getName());
        return object;
    } }

applicationContext.xml

声明业务对象

<bean name="s" class="com.how2java.service.ProductService"> </bean> 

声明日志切面

<bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>

指定核心业务功能

<aop:pointcut id="loggerCutpoint"

            expression=
            
            "execution(* com.how2java.service.ProductService.*(..)) "/>

这一句是声明切入点。

  • 切入点的 id 叫 loggerCutPoint ,用来标记这个切入点,
  • 这个expression表示:满足expression中的方法调用之后,就会去进行切面操作,类似于触发了切面:
    – 第一个 * 代表返回任意类型 com.how2java.service.ProductService.* 表示包名以
    – com.how2java.service.ProductService 开头的类的任意方法(第二个*表示任意方法)
    – (…) 表示方法的参数是任意数量和类型

简单说就是,只要com.how2java.service这个包中的ProductService类的任意一个函数被调用,不管你的返回值是什么,都会触发开关,我就会去执行切面,也就是辅助功能,但是辅助功能是什么呢,就是下面两句:

指定辅助功能

<aop:aspect id="logAspect" ref="loggerAspect">

  <aop:after pointcut-ref="loggerCutpoint" method="log"/>

</aop:aspect>

这两句是定义了一个切面,上面说只要触发开关,就会去执行切面

  • id代表这个切面的名字,ref就是指的方法所在的类,method代表的就是方法的名字,

  • pointcut-ref=“loggerCutpoint” 这个就是表示我这个切面是和上面的切点关联起来的(一个切点是可以关联多个切面的,一个切面只能关联一个方法),只要上面的切点被触发,我就会到这里来执行一些辅助功能

  • after表示在切入点触发之后来执行我这个中断,当然也有before,一共有五个before,after,After-returning,After-throwing,Around。

  • 在 method 参数后面,还可以加上参数列表。

tips
如果还是差点感觉的话推荐看一下这个帖子(实在写的详细,优秀):

然后通过aop:config把业务对象与辅助功能编织在一起。

<?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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context     
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  
    <bean name="c" class="com.how2java.pojo.Category">
        <property name="name" value="yyy" />
    </bean>
 
    <bean name="p" class="com.how2java.pojo.Product">
        <property name="name" value="product1" />
        <property name="category" ref="c" />
    </bean>
     
    <bean name="s" class="com.how2java.service.ProductService">
    </bean>   
     
    <bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>
     
    <aop:config>
        <aop:pointcut id="loggerCutpoint"
            expression=
            "execution(* com.how2java.service.ProductService.*(..)) "/>
             
        <aop:aspect id="logAspect" ref="loggerAspect">
            <aop:around pointcut-ref="loggerCutpoint" method="log"/>
        </aop:aspect>
    </aop:config>    
  
</beans>

TestSpring.java

package com.how2java.test;
  
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.how2java.service.ProductService;
  
public class TestSpring {
  
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "applicationContext.xml" });
        ProductService s = (ProductService) context.getBean("s");
        s.doSomeService();
    }
}

参考博文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值