Spring之AOP

目录

1、AOP基本概念

2、AOP底层原理

3、AOP相关术语 

4、Spring中AOP操作

5、AOP操作(AOP注解)

6、AOP操作(AOPXML配置)


1、AOP基本概念

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

2、不通过修改源代码的方式添加新功能

2、AOP底层原理

1、AOP底层使用了动态代理

-动态代理有两种情况 :有接口和无接口情况

第一种情况,有接口情况,使用JDK动态代理

-获取代理对象需使用Proxy类要调用里面newProxyInstance方法

Object object = newProxyInstance(ClassLoader loader,class<?>[] interfaces,InvocationHandler h)

-方法有三个参数 :

第一个参数:类加载器

第二个参数:增强方法所在类,这个类实现的接口,支持多个接口

第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强方法

代码演示:

//创建UserDAO接口的实现类并重写方法
public class UserDAOImpl implements UserDAO {
    @Override
    public int add(int a, int b) {
        return a+b;
    }

    @Override
    public String update(String id) {
        return id;
    }
}
//创建代理类
public class JDKProxy {
    public static void main(String[] args) {
        //Class类型的接口数组
        Class[] interfaces = {UserDAO.class};
        //需要增强的实现类对象
        UserDAOImpl userDAO = new UserDAOImpl();
        UserDAO dao = (UserDAO) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDAOProxy(userDAO));
        int result = dao.add(1, 2);
        System.out.println(result);
    }
}

//创建代理对象代码
class UserDAOProxy implements InvocationHandler{
    //1.把创建的是谁的代理对象,把谁传进来
    //有参构造
    private Object obj;
    public UserDAOProxy(Object object){
        this.obj = object;
    }
    //增强逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法执行之前处理
        System.out.println("方法之前执行..."+method.getName()+":传递参数..."+ Arrays.toString(args));
        //增强的方法执行
        Object res = method.invoke(obj, args);
        //方法执行之后处理
        System.out.println("方法执行之后执行..."+obj);
        return res;
    }
}

第二种情况,没有接口情况,使用CGLIB动态代理

3、AOP相关术语 

1、连接点

        类里那些方法可以被增强,这些方法就叫做连接点

2、切入点

        实际真正被增强的方法就叫做切入点

3、通知(增强)

    (1)实际增强的逻辑部分称为通知

    (2)通知有多种类型:

        -前置通知

        -后置通知

        -环绕通知

        -异常通知

        -最终通知

4、切面

        把通知应用到切入点的过程就叫做切面

4、Spring中AOP操作

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

1、什么是AspectJ

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

2、基于AspectJ实现AOP操作的方式

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

  (2)基于注解方式实现(常用)

3、想要使用AspectJ需要引入相关依赖

4、切入点表达式

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

   (2)语法结构:

        execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))

5、AOP操作(AOP注解)

1、在Spring配置文件中,开启注解扫描

2、使用注解创建User和UserProxy对象

3、在增强类上面添加注解@Aspect

4、在Spring配置文件中开启生成代理对象 

5、配置不同类型的通知(增强类里,通知方法上方添加注解,使用切入点表达式)

6、多个增强类对一个方法进行增强可以使用@Order(数字类型数值)控制优先级,数值越小优先级越高

 -添加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 https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="com.atqjb.Spring5"></context:component-scan>
    <!--开启AspectJ生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
//完全注解开发不需要创建xml配置文件
//创建配置类
@Configuration
@ComponentScan(basePackages = {"com.atqjb.Spring5"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {}

 -使用注解创建User和UserProxy对象,并使用@Aspect指定增强类t

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

-在增强类里添加注解使之成为代理类

-在方法上添加注解使之成为不同增强方法 

package com.atqjb.Spring5;
//增强类
@Component
@Aspect  //生成代理对象
public class UserProxy {
    //前置通知
    //在add方法之前执行
    //@Before注解表示前置通知
    @Before(value = "execution(* com.atqjb.Spring5.User.add(..))")
    public void before(){
        System.out.println("before...");
    }
    //最终通知,执行增强方法后执行,不管有没有异常都执行
    @After(value = "execution(* com.atqjb.Spring5.User.add(..))")
    public void after(){
        System.out.println("after...");
    }
    //后置通知,返回值之后执行,增强方法有异常不执行
    @AfterReturning(value = "execution(* com.atqjb.Spring5.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning...");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.atqjb.Spring5.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing...");
    }
    //环绕通知,在增强方法之前之后都执行
    @Around(value = "execution(* com.atqjb.Spring5.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("环绕前...");
        //被增强的方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕后...");
    }
}

 优化:相同切入点抽取

//相同切入点抽取
@Pointcut(value = "execution(* com.atqjb.Spring5.User.add(..))")
public void pointdemo(){}
//前置通知
//在add方法之前执行
//@Before注解表示前置通知
@Before(value = "pointdemo()")//调用切入点抽取方法即可
public void before(){
    System.out.println("before...");
}

6、AOP操作(AOPXML配置)

<!--创建对象-->
<bean id="book" class="com.atqjb.Spring.Book"/>
<bean id="bookProxy" class="com.atqjb.Spring.BookProxy"/>

<!--配置aop增强-->
<aop:config>
    <!--切入点-->
    <aop:pointcut id="p" expression="execution(* com.atqjb.Spring.Book.buy(..))"/>
    <!--配置切面-->
    <aop:aspect ref="bookProxy">
        <!--增强作用在具体方法上-->
        <aop:before method="before" pointcut-ref="p"/>
    </aop:aspect>
</aop:config>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值