Spring——AOP

Spring——AOP

概念——什么是AOP

Aspect Oriented Programming:面向切面编程

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

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

在这里插入图片描述

AOP底层原理

AOP底层使用动态代理
  1. ​ 有两种情况动态代理

    有接口情况,使用JDK动态代理:创建接口实现类代理对象,增强类的方法

在这里插入图片描述

没有接口情况:使用CGLIB动态代理:创建子类的代理对象,增强类的方法

在这里插入图片描述

JDK动态代理实现

  1. 调用newProxyInstance方法

    start object newProxyInstance(Classloader loader,类<?>[ ] interfaces,InvocationHandler h);

    参数1:类加载器

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

    参数3:实现这个接口InvocationHandle,创建代理对象,写增强的部分

  2. JDK代理代码

    创建接口,定义方法

    创建实现类,实现方法(将方法功能增强)

    使用Proxy创建接口代理对象

  3. 实现过程

    接口(UserDao.interface)——实现接口类(UserDaoImpl.java)——代理类(JDKProxy)

    接口类

    public interface UserDao {
        public int add(int a,int b);
        public String update(String id);
    }
    

    实现接口类

    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[] interfaces={UserDao.class};
            UserDaoImpl userDao=new UserDaoImpl();
            UserDao dao=(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,new UserDaoProxy(userDao));
            int result= dao.add(4,2);
            System.out.println("result:"+result);
        }
    }
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{
        //把创建的是谁的代理对象,把谁传递过来
        //有参数构造传递
        private Object obj;
        public UserDaoProxy(Object obj){
            this.obj=obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //方法之前
            System.out.println("方法执行之前..."+method.getName()+":传递的参数..."+ Arrays.toString(args));
            //被增强的方法执行
            Object result=method.invoke(obj,args);
            //方法之后
            System.out.println("方法之后执行..."+obj);
            return result;
        }
    }
    

Aop常用术语

  1. 连接点:类里可被增强的方法称为连接点

  2. 切入点:实际真正被增强的方法称为切入点

  3. 通知(增强):实际增强的逻辑部分称为通知增强

    前置通知、后置通知、环绕通知、异常通知、最终通知

  4. 切面:是动作,把通知应用到切入点过程

AOP操作

  1. Spring框架一般基于AspectJ实现AOP操作

    什么是AspectJ?

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

  2. 基于AspectJ实现AOP操作

    基于xml配置文件实现

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

  3. 在项目工程文件中引入AOP依赖包

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k6rJFycJ-1657181125029)(C:\Users\罗兴风\AppData\Roaming\Typora\typora-user-images\image-20220707121648486.png)]

  4. 切入点表达式

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

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

    例1:execution(* aop.bookdao.add(…))

    例2:execution(* aop.bookdao.*(…))

AOP操作(Aspect注解)

  1. 创建类,在类里面定义方法(User)

    public class User {
        public void add(){
            System.out.println("add...");
        }
    }
    
  2. 创建增强类,编写增强逻辑(UserProxy)

    在增强类里面,创建方法,让不同方法代表不同通知类型

    public class UserProxy {
        public void before(){
            System.out.println("before...");
        }
    }
    
  3. 进行类通知的配置

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

    使用注解创建上述对象

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

    @Component
    public class User {
        public void add(){
            System.out.println("add...");
        }
    }
    
    @Component
    @Aspect//生成代理对象
    public class UserProxy {
        public void before(){
            System.out.println("before...");
        }
    }
    

    在spring配置文件中开启生成代理对象(此处也可通过注解类开启组件扫描和开启Aspect生成代理对象)

    注解类

    @Configuration
    @ComponentScan(basepackage={src.aop})
    @EnableAspectJAutoProxy(proxyTargetClass=true)
    public class configAop{
    }
    

    配置文件xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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
                               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="src.aop"></context:component-scan>
    <!--    开启Aspect生成代理对象-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>
    
  4. 配置不同类型的通知

    1. 在增强类里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
    @Component
    @Aspect//生成代理对象
    public class UserProxy {
        //前置通知,Before注解表示前置通知
        @Before(value = "execution(* src.aop.User.add(..))")
        public void before(){
            System.out.println("before...");
        }
    }
    

    通知(增强)类型

    @Component
    @Aspect//生成代理对象
    public class UserProxy {
        //前置通知,Before注解表示前置通知
        @Before(value = "execution(* src.aop.User.add(..))")
        public void before(){
            System.out.println("before...");
        }
        @After(value = "execution(* src.aop.User.add(..))")
        public void after(){
            System.out.println("after...");
        }
        @AfterReturning(value = "execution(* src.aop.User.add(..))")
        public void afterReturning(){
            System.out.println("afterReturning...");
        }
        @AfterThrowing(value = "execution(* src.aop.User.add(..))")
        public void afterThrowing(){
            System.out.println("after throwing...");
        }
        @Around(value = "execution(* src.aop.User.add(..))")
        public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
            System.out.println("环绕前...");
            proceedingJoinPoint.proceed();
            System.out.println("环绕后...");
        }
    }
    

    输出结果

在这里插入图片描述

  1. 相同切入点的抽取

    @Pointcut(value = "execution(* src.aop.User.add(..))")
    public void pointdemo(){   
    }
    
     @Before(value = "pointdemo()")
    public void before(){
        System.out.println("before...");
    }
    
  2. 有多个增强类对同一个方法进行增强,设置增强类优先级

    在增强类上面添加注解@Order(数字类型值),数值越小,优先级越小

    @Component
    @Aspect
    @Order(1)
    public class OtherProxy {
        @After(value = "execution(* src.aop.User.add(..))")
        public void after(){
            System.out.println("OtherProxy...");
        }
    }
    
    @Component
    @Aspect//生成代理对象
    @Order(3)
    public class UserProxy 
    

    输出结果

在这里插入图片描述

AOP操作(AspectJ配置文件,一般常用注解方式)

  1. 创建两个类,增强类和被增强类,创建方法

    public class book {
        public void buy(){
            System.out.println("buy...");
        }
    }
    
    public class bookProxy {
        public void before(){
            System.out.println("before...");
        }
    }
    
  2. 在spring配置中创建两个类对象

        <bean id="book" class="src.aopxml.book"></bean>
        <bean id="bookProxy" class="src.aopxml.bookProxy"></bean>
    
  3. 在spring配置文件中配置切入点

<aop:config>
    <!--配置切入点-->
    <aop:pointcut id="p" expression="execution(* src.aopxml.book.buy(..))"/>
    <!--配置切面-->
    <aop:aspect ref="bookProxy">
        <aop:before method="before" pointcut-ref="p" />
    </aop:aspect>
</aop:config>
  <bean id="bookProxy" class="src.aopxml.bookProxy"></bean>

3. 在spring配置文件中配置切入点

```xml
<aop:config>
 <!--配置切入点-->
 <aop:pointcut id="p" expression="execution(* src.aopxml.book.buy(..))"/>
 <!--配置切面-->
 <aop:aspect ref="bookProxy">
     <aop:before method="before" pointcut-ref="p" />
 </aop:aspect>
</aop:config>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rush006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值