Spring_AOP

一、AOP概述(什么是AOP)

 (1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

(3)使用登录例子说明 AOP

 二、AOP底层原理(动态代理)

        动态代理的实现(调用newProxyInstance方法实现:

        newProxyInstance方法介绍:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)

        静态方法,有三个形参

        (1)ClassLoader loader:获取运行时类的加载器

        (2)Class<?>[] interfaces:获取运行类的接口

        (3)InvocationHandler h:实现这个接口 InvocationHandler,创建代理对象,写增强的部分

举例说明:

接口:定义生产衣服的规范

代理类:LINING公司、ANTA公司

被代理类:生产衣服的工厂

                被代理的方法:生产(LINING/ANTA)公司的衣服

增强的方法:衣服被生产完后需要进行包装

动态代理的代码:

接口:

//生产衣服的规范
public interface norms {
 public void production();
}

被代理类:

public class Factory implements norms  {
 @Override
 public void production() {
 System.out.println("被代理类(生产衣服的工厂)开始生产衣服");
 }
}

动态代理产生被代理类(重点):

//创建被代理类:LINING ANTA 公司
public class ProxyFactory {
    public static void main(String[] args) {
        //创建接口实现类(Factory)的代理对象
        //.class 获取运行时类 .class.getClassLoader() 获取类的加载器
        Factory factory = new Factory();
        Class[] interfaces = {norms.class};
        myInvocationHander myInvocationHander = new myInvocationHander(factory);
        norms LINING = (norms) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, myInvocationHander);
        //调用方法时去执行myInvocationHander 类中的invoke方法
        LINING.production();

    }
}
class myInvocationHander implements InvocationHandler {

    //1.把创建的是谁的代理对象,就把谁传进来
    private Object obj;//obj表示被代理对象
    public myInvocationHander(Object obj) {//传入代理类的对象
        this.obj = obj;
    }

    //增强的逻辑
    @Override
    //proxy 表示代理类的对象 method表示代理类执行的方法 args表示代理类执行的方法的参数
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        //method.getName() 表示获取执行代理类的方法的名称
        System.out.println("执行被代理类方法" +method.getName() + "前的操作");
        //执行被代理类的方法
        //执行代理类方法的被代理类中的同名方法
        Object invoke = method.invoke(obj, args);
        //方法之后
        System.out.println("衣服生产完后进行包装");
        return invoke;
    }
}

运行结果:

执行被代理类方法production前的操作
被代理类(生产衣服的工厂)开始生产衣服
衣服生产完后进行包装

 三、AOP中的术语

        1、连接点:类中那些方法可以被增强,这些方法被称为连接点

        2、切入点:实际中被增强的方法,被称为切入点,如上述中生产衣服的方法

        3、通知:实际被增强的逻辑部分,如上述的包装

              (1)前置通知

              (2)后置通知

              (3)环绕通知

              (4)异常通知

              (5)最终通知

        4、切面:将通知应用到切入点的过程

四、AOP的实现基础

        1、Spring 框架一般都是基于 AspectJ 实现 AOP 操作

                (1)AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使 用,进行 AOP 操作

        2、基于 AspectJ 实现 AOP 操作

                (1)基于 xml 配置文件实现(了解)

                (2)基于注解方式实现(重点)

        3、引入依赖

        

         4、切入点表达式

                (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强

                (2)语法结构: execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])

        举例 1:对 BookDao 类里面的 add 进行增强 execution(* dao.BookDao.add(..))

        举例 2:对 BookDao 类里面的所有的方法进行增强 execution(* dao.BookDao.* (..))

        举例 3:对dao 包里面所有类,类里面所有方法进行增强 execution(* dao.*.* (..))

五、AOP的实现步骤

        1、配置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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <!--开启组件扫描
        1.扫描多个包 多个包使用逗号隔开
        2.扫描包上层目录
     -->
    <context:component-scan base-package="aop_annotation"></context:component-scan>
    <!--开启Aspectj生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

        2、创建被增强类,在类中创建方法(类似登录界面原始的步骤)

//被增强类
@Component
public class User {
    public void add(){
        System.out.println("add......");
    }
}

        3.创建增强类(类似登录界面判断是否是管理人员的操作)

//增强类
@Component//创建类的对象
@Aspect//生成代理对象 使用注解Aspect实现
@Order(1)//设置增强类的优先级 使用注解order实现 数字越小,优先级越高
public class UseProxy {

    //相同切入点抽取 利用注解Pointcut实现
    @Pointcut(value = "execution(* aop_annotation.User.add(..))")
    public void same(){

    }

    //前置通知 利用注解Before实现
    //execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])
    @Before(value = "same()")//抽取befo抽取
    public void before(){
        System.out.println("before");
    }

    //最终通知 利用注解After实现(方法执行后 方法参数返回前)
    //execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])
    @After(value = "execution(* aop_annotation.User.add(..))")
    public void After(){
        System.out.println("After");
    }

    //异常通知 利用注解AfterThrowing实现
    //execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])
    @AfterThrowing(value = "execution(* aop_annotation.User.add(..))")
    public void AfterThrowing(){
        System.out.println("AfterThrowing");
    }


    //后置通知(方法执行后 方法返回后)
    //execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])
    @AfterReturning(value = "execution(* aop_annotation.User.add(..))")
    public void AfterReturning(){
        System.out.println("AfterReturning");
    }

    //环绕通知 利用注解Around实现
    //execution 表示切入点表达式 execution([权限修饰符(可省略)][返回类型(* 表示任意返回类型)][类全路径][方法名(*表示所有的方法)][形参列表(.. 表示任意)])
    @Around(value = "execution(* aop_annotation.User.add(..))")
    public void Around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前");
        //被增强的方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之前");
    }
}

六、完全注解开发实现AOP

        创建配置类实现XML配置文件的功能

//代替xml文件进行组件扫描
@Configuration
@ComponentScan("aop_annotation")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值