【Spring】AOP原来如此

发布时间:2024年01月01日

AOP概述

什么是AOP的技术?

  • 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
  • AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
  • AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范
  • 通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术
  • AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型
  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

AOP:面向切面编程.(思想.---解决OOP遇到一些问题)

????????AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)

为什么要学习AOP,可以在不修改源代码的前提下,对程序进行增强!!


说到增强你觉得AOP和谁比较像? 没错是代理 ,不了解看这篇文章00=》【javaSE】代理并不难-CSDN博客


AOP的底层原 理

JDK的动态代理技术

? 1、为接口创建代理类的字节码文件

? 2、使用ClassLoader将字节码文件加载到JVM

? 3、创建代理类实例对象,执行对象的目标方法

cglib代理技术

1、创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器

2、在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))

3、创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))

4、创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用


?AOP相关的术语

  • Joinpoint(连接点) 所谓连接点是指那些被拦截到的点。在spring,这些点指的是方法,因为spring只支持方法类型的连接点
  • Pointcut(切入点) -- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
  • Advice(通知/增强)-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
  • Target(目标对象)-- 代理的目标对象
  • Weaving(织入)-- 是指把增强应用到目标对象来创建新的代理对象的过程
  • Proxy(代理)-- 一个类被AOP织入增强后,就产生一个结果代理类
  • Aspect(切面)-- 是切入点和通知的结合,以后咱们自己来编写和配置的

基于代理类的AOP

Spring的AOP代理默认用的就是JDK代理方式来实现的,在Spring中,ProxyFactoryBean是创建AOP代理的最基本方法(不常用,后面有更好的方法)

ProxyFactoryBean

ProxyFactoryBean是FactoryBean接口的实现类,FactoryBean负责实例化一个Bean,而ProxyFactoryBean负责为其他Bean创建代理实例。

ProxtFactoryBean类的常用配置属性

target

代理的目标对象

proxyInterfaces

代理要实现的接口,如果有多个接口,可以使用一些形式赋值

...

proxyTargetClass

是否对类代理而不是接口,设置为true时,使用CGLIB代理

interceptorNames

需要织入目标的Advice

singleton

返回的代理是否为单实例,默认为true

optimize

设置为true,强制使用CGLIB

下面是一个典型例子:

导包

在核心jar包基础上导入AOP的jar包,

  • Spring-aop-4.3.6.RELEASE.jar
  • aopalliance-1.0.jar
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>

编写配置类?

package com.aqiuo.factorybean;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//切面类。实现了MethodInterceptor方法拦截器接口
public class MyAscpect implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
            
        check_permissions();
        Object object= mi.proceed();
        log();
        return object;
    }
    //增强的方法体--通知
    public void check_permissions() {
        System.out.println("模拟权限检查");
    }
//增强的方法体--通知
    public void log() {
        System.out.println("模拟日志记录");
    }

}

?编写配置文件

//application.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:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd " > 
          
           <!-- 目标类 用的是jdk的对象 -->
    <bean id="accountService" class="com.aqiuo.service.impl.AccountServiceImpl"></bean>
    <!-- 切面类 -->
    <bean id="myAspect" class="com.aqiuo.aspect.MyAspect02"></bean>

    <!-- 使用Spring工厂定义一个名称为userDaoProxy的代理对象 -->
    <bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 指定代理要实现的接口 -->
        <property name="proxyInterfaces" value="com.aqiuo.service.AccountService"></property>
        <!-- 指定目标对象 -->
        <property name="target" ref="accountService"></property>
        <!-- 指定切面,执行环绕通知 -->
        <property name="interceptorNames" value="myAspect"></property>
        <!-- 指定代理方式 -->
        <property name="proxyTargetClass" value="true"></property>
    </bean>
       
   
</beans>


//测试

强调:获取的对象是代理之后的对象,不是原来的目标对象,获取原来的目标对象是不会有增强的?

    @Test
    public void run2() throws SQLException {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService= (AccountService) applicationContext.getBean("userDaoProxy");

        accountService.pay(100,1,2);

    }

在上述代码中,首先通过bean元素定义了目标类和切面,然后使用ProxyFactoryBean类定义了代理对象。

????????在定义的代理对象中,分别通过子元素指定了代理实现的接口、代理的对象、需要织入的目标类的通知,已经代理方式


?下篇文章讲解AOP的AspectJ,AspectJ是一个居于JAVA开发的AOP框架》》框架

文章来源:https://blog.csdn.net/m0_62645012/article/details/135323539
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。