AOP复习

AOP面向切面编程

一、AOP概念简介

​ AOP是面向切面编程的简称,通俗的说就是在不改变源码的基础上实现对功能的增加

二、AOP底层原理

​ AOP底层使用了动态代理,而动态代理有两种情况,分别是有接口的情况和没有接口的情况

①有接口的情况:

​ 通过创建接口实现类的代理对象实现:

在这里插入图片描述

②没有接口的情况:

​ 通过创建该类的子类的代理对象实现:

在这里插入图片描述

③有接口的动态代理代码实现:g

​ 1.接口:

public interface UserDao {

    public void add();
}

​ 2.实现类:

public class UserDaoImpl implements UserDao {

    @Override
    public void add() {
        System.out.println("add...");
    }
}

​ 3.实现增强:

public class UserDaoImplProxy implements InvocationHandler {

    //内置一个属性,该属性为要被增强的类
    private Object object;

    public UserDaoImplProxy(Object object) {
        this.object = object;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //增强逻辑
        System.out.println("前置增强");

        //原来逻辑
        method.invoke(object, args);

        //增强逻辑
        System.out.println("后置增强");

        return null;
    }
}

​ 4.创建接口实现类的代理对象:

    public void test(){

        Class[] classes = {UserDao.class};

        UserDao userDao = new UserDaoImpl();

        //使用Proxy类来实现
        UserDao userDao1 = (UserDao) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), classes, new UserDaoImplProxy(userDao));

        userDao.add();
        System.out.println(".......");
        userDao1.add();
    }

​ 创建接口实现类的代理对象,使用的Proxy类中的newProxyInstance方法,其中有三个参数:

​ 第一个为类的加载器,该值为你在创建代理对象时所在的类的类的加载器;

​ 第二个为一个Class类的数组,该数组的值为你要实现动态代理的实现类的接口的类型类;

​ 第三个为一个InvocationHandler接口的实现类的实例,你有创建一个类来实现该接口,在在接口中有一个invoke方法要实现,在该方法中就可以加入增强你的逻辑;

三、AOP常用术语:
public class Person {

    private String name;
    private Integer id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}    

​ (1)接入点:意思是可以实现增强的方法,如其中的getName、getId等方法;

​ (2)切点:意思是实现了增强的方法,如getNamePlus,对应的切点为getName;

​ (3)通知:意思是用来增强的代码,如getNamePlus中除去getName的部分都是通知;

​ (4)切面:是指一个动作,即将增强代码加入到其中的过程称为切面;

四、AOP的注解操作
①准备工作:

​ 第一步导入依赖:

在这里插入图片描述

​ 第二步,熟悉切入点表达式

​ 格式如下:Execution([权限修饰符] [返回值类型] [全类名] [方法名] [参数列表])

​ 一般格式为Execution(*空格com.lazy.bean.Person.say(…))

​ 例一:对指定包内的指定类的指定方法进行增强

Execution(* com.lazy.bean.Person.say(..))

​ 例二:对指定包内的指定类所有方法进行增强

Execution(* com.lazy.bean.Person.*(..))

​ 例三:对指定包内的所有类的所有方法进行增强

Execution(* com.lazy.bean.*.*(..))
②操作流程

​ 第一步,创建类

public class UserDaoImpl implements UserDao {

    public void add(){
        System.out.println("add...");
    }
}

​ 第二步,创建增强类

public class UserDaoPlus {

    //前置通知
    public void before(){
        System.out.println("before...");
    }
    
}

​ 第三步,进行通知配置(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/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<context:component-scan base-package="com.lazy.aop2"></context:component-scan>

​ 使用注解创建对象:

@Component
public class UserDaoImpl implements UserDao {

​ 使用@Aspect注解标识增强对象:

@Component
@Aspect
public class UserDaoPlus {

​ 开启代理对象:

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

​ 第四步,将实现对被增强方法的不同通知:

    //前置通知
    @Before(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void before(){
        System.out.println("before...");
    }

​ 补充实现完全注解开发:

@Configuration
@ComponentScan(basePackages = "com.lazy.aop2.bean")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AOPConfig {
}
③四种通知介绍即操作

​ 通知中有四种类型分别是:

​ (1)前置通知,即在要增强方法前的代码;

    //前置通知
    @Before(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void before(){
        System.out.println("before...");
    }

​ (2)后置通知,在要增强方法后的代码(return语句执行后);

    //后置通知
    @AfterReturning(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void afterReturn(){
        System.out.println("afterReturn....");
    }

​ (3)环绕通知,在要增强的方法前后执行;

    //环绕通知
    @Around(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around...");
        proceedingJoinPoint.proceed();
        System.out.println("around...");
    }

​ (4)异常通知,在要增强的方法发生异常之后执行;

    //异常通知
    @AfterThrowing(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing");
    }

​ (5)最终通知,不论方法是否异常都将执行;

    //最终通知
    @After(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void after(){
        System.out.println("after...");
    }

执行结果如下:

在这里插入图片描述

​ 发生异常时如下:

在这里插入图片描述

④抽取切入点表达式
    @Pointcut(value = "execution(* com.lazy.aop2.bean.UserDaoImpl.add(..))")
    public void symbol(){};

    //前置通知
    @Before(value = "symbol()")
    public void before(){
        System.out.println("before...");
    }
⑤多个增强类作用同一个类的方法时的顺序控制:

​ 可以在各个增强类前加上@Order注解,在注解中加入数值,数值越小表示优先级越高

@Order(1)
public class UserDaoPlus {
五、AOP配置文件操作:
<!--  创建对象  -->
    <bean id="userDaoImpl" class="com.lazy.aop3.bean.UserDaoImpl"></bean>
    <bean id="userDaoImplPlus" class="com.lazy.aop3.bean.UserDaoPlus"></bean>

<!--  标识增强类  -->
    <aop:config>
<!--   创建切入点     -->
        <aop:pointcut id="p" expression="execution(* com.lazy.aop3.bean.UserDaoImpl.add(..))"/>
<!--   配置切面     -->
        <aop:aspect ref="userDaoImplPlus">
<!--    配置通知        -->
            <aop:before method="before" pointcut-ref="p"></aop:before>
        </aop:aspect>
    </aop:config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值