AOP面向切面编程

1、AOP 简介

1.1 什么是 AOP

AOP 的全称是 Aspect Oriented Programming,即面向切面编程,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。

AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。

目前最流行的 AOP 技术有两个,分别为 Spring 框架的 AOP 和 AspectJ 框架。

1.2 什么是面向切面编程

把一个个的横切关注点放到某个模块中去,称之为切面。每个切面影响业务的一种功能,切面的目的就是为了功能增强,将需要增强的方法做成切面,实现对业务的增强,就是面向切面编程。

面向切面编程的目的:将与业务本身无关,却被业务模块所共同调用的功能代码封装成切面,以减少系统的重复代码,降低耦合,提高可扩展性。

面向切面编程的优势:把多个方法前/后的共同代码抽离出来,使用动态代理机制来控制,先执行抽离出来的代码,再执行每一个真实方法。

 

2、AOP 术语

为了更好地理解 AOP,就需要对 AOP 的相关术语有一些了解,这些专业术语主要包含Joinpoint、Pointcut、Advice、Target、Weaving、Proxy 和 Aspect,它们的含义如下表所示。

 

 

3、Spring AOP 模块

3.1 Spring AOP 模块中的通知类型

 

3.2 Spring AOP 模块的使用

在使用 Spring 框架的 AOP 模块开发 AOP 时,需要添加核心容器的 jar 包以及 aop 的 jar包。

注意:ThrowsAdvice 接口是一个标识接口没有任何抽象方法。如果通知类型定义为异常通知,那么除了要实现 ThrowsAdvice 以外,还需要在切面中添加下面 4 个方法中的一个,并在该方法中实现具体的增强处理。

public void afterThrowing(Exception ex)

public void afterThrowing(RemoteException)

public void afterThrowing(Method method, Object[] args, Object target, Exception ex)

public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

3.2.1 创建切面

 

package com.dyh.aspect;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
import org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 切面类:配置前置通知、后置通知,环绕通知,异常通知
 */
public class MyAspect implements MethodBeforeAdvice, AfterReturningAdvice, MethodInterceptor,ThrowsAdvice {

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("Before...."+method.getName());
    }

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("After...."+method.getName());
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Around  .....Before"+methodInvocation.getMethod().getName());
        //执行目标方法
        Object  obj  = methodInvocation.proceed();
        System.out.println("Around.....After"+methodInvocation.getMethod().getName());
        return  obj;
    }

    public void afterThrowing(Exception ex){
        System.out.println(ex.getMessage());
    }
}

3.2.2 配置切面

Spring 的 AOP 模块实现 AOP 编程的方式:

使用 org.springframework.aop.framework.ProxyFactoryBean 工厂对象创建代理对象。

3.2.2.1 创建目标对象

public interface UsersService {
    void add();
    void modify();
}

UserServiceImpl.java实现类:

public class UsersServiceImpl implements UsersService {
    @Override
    public void add() {
        System.out.println("执行插入数据的业务逻辑");
        throw new RuntimeException("出现异常。。。。。。。");
    }

    @Override
    public void modify() {
        System.out.println("执行修改数据的业务逻辑");
    }
}

3.2.2.2 修改 Spring 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <!--配置切面类 -->
    <bean id="myAspect" class="com.dyh.aspect.MyAspect">

    </bean>

    <!--配置UserServicebean-->
    <bean id="usersService" class="com.dyh.service.impl.UsersServiceImpl">

    </bean>

    <!--配置切面-->
    <bean id="usersServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置目标对象实现的接口-->
        <property name="proxyInterfaces" value="com.dyh.service.UsersService" />
        <!--配置代理的目标对象-->
        <property name="target" ref="usersService" />
        
        <!--配置切面对象-->
        <property name="interceptorNames">
            <list>
                <value>myAspect</value>
            </list>
        </property>
        <!--如何生成代理对象  true:使用 CGLIB,false 使用 JDK 的  Proxy-->
        <property name="proxyTargetClass" value="true" />
    </bean>
</beans>

3.2.2.3 创建测试类

public class TestAOP {
    public static void main(String[] args) {
        ApplicationContext applicationContext  =  new
                ClassPathXmlApplicationContext("application_context.xml");
        UsersService usersService  =  (UsersService)
                applicationContext.getBean("usersServiceProxy");
        usersService.add();
    }
}

3.3 Spring AOP 模块的使用案例

需求:要求在业务层的 updateUsers 方法执行之前,将 UserName 参数转换大写。

3.3.1 修改业务层

public interface UsersService {
    void add();
    void modify(String userName);
}

UsersServiceImpl.java

  @Override
    public void modify(String userName) {
        System.out.println("执行修改数据的业务逻辑");
        System.out.println(userName);
    }

3.3.2 创建切面

public class ToUpCaseAspect implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object[] args = methodInvocation.getArguments();
        args[0] = ((String)args[0]).toUpperCase();
        Object obj = methodInvocation.proceed();
        return  obj;
    }
}

3.3.3 配置切面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <!--配置切面类 -->
    <bean id="myAspect" class="com.dyh.aspect.MyAspect">

    </bean>
    <!--配置切面类 -->
    <bean id="toUpCaseAspect" class="com.dyh.aspect.ToUpCaseAspect">

    </bean>

    <!--配置UserServicebean-->
    <bean id="usersService" class="com.dyh.service.impl.UsersServiceImpl">

    </bean>

    <!--配置切面-->
    <bean id="usersServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置目标对象实现的接口-->
        <property name="proxyInterfaces" value="com.dyh.service.UsersService" />
        <!--配置代理的目标对象-->
        <property name="target" ref="usersService" />
        
        <!--配置切面对象-->
        <property name="interceptorNames">
            <list>
                <value>myAspect</value>
                <value>toUpCaseAspect</value>
            </list>
        </property>
        <!--如何生成代理对象  true:使用 CGLIB,false 使用 JDK 的  Proxy-->
        <property name="proxyTargetClass" value="true" />
    </bean>
</beans>

修改测试类:

public class TestAOP {
    public static void main(String[] args) {
        ApplicationContext applicationContext  =  new
                ClassPathXmlApplicationContext("application_context.xml");
        UsersService usersService  =  (UsersService)
                applicationContext.getBean("usersServiceProxy");
        //usersService.add();
        usersService.modify("admin");
    }
}

运行结果如下:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值