SpringAOP原理

一.SpringAop是什么?

Aop(Aspect Oriented Programming)面向切面编程,指的是抽取重复加在业务前后的代码,通过切面的方法应用在目标方法上。比如一些我们需要在某个方法前后记入日志,我们就可以使用aop动态代理来实现方法的增强。

二.AOP核心概念

1.连接点:连接点是一个非常抽象的概念,它表示一个时机,比如某个方法方法执行前后,或者方法出现异常时都是连接点。但在springAOP中仅仅支持方法的连接点。

2.通知:通知是指在连接点处执行的某段代码,所有被通知注解标注的方法都是通知。

3.切点:切点是用来匹配连接点的,下面通过例子说明

4.目标对象:指需要处理的目标类。如果没有AOP的支持,目标对象需要独立王朝所有业务逻辑。目标方法通常指切点映射的方法

5.切面:切面指的是AOP处理的类,此类封装了许多其他类需要植入的方法。

6.织入:织入是指将通知添加到目标类具体的连接点的过程。

三.实例

下面演示通过AOP来实现日志管理的例子:

BookHandel类

package com.example.aop;
import org.springframework.stereotype.Component;
@Component
public class BookHandel {
    private String nime;

    public String getNime() {
        return nime;
    }

    public void setNime(String nime) {
        this.nime = nime;
    }
    public BookHandel(String nime) {
        this.nime = nime;
    }
    public  void  addbook(){
        System.out.println("添加对象");
    }
    public static void main(String[] args) {
    }
}

Logaspect类

package com.example.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Aspect
@Component
@EnableAspectJAutoProxy
public class Logaspect {
    @Before("execution(* com.example.aop.BookHandel.addbook())")
    public void dealAddlog(JoinPoint joinPoint){
        System.out.println("开始添加");
    }
    @AfterThrowing("execution(* com.example.aop.BookHandel.addbook())")
    public void dealAfeterReturn(JoinPoint joinPoint){
        System.out.println("添加失败");
    }
    @AfterReturning("execution(* com.example.aop.BookHandel.addbook())")
    public void dealException(JoinPoint joinPoint){
        System.out.println("添加成功");
    }
}

XML配置bean

<?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 https://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.example">
    </context:component-scan>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <bean id="BookHandel" class="com.example.aop.BookHandel">
        <constructor-arg name="nime" value="java">
        </constructor-arg>
    </bean>
</beans>

其中Logaspect就是一个切面类,通过@Aspect注解标注,里面有许多通知,通知包括前置通知、后置通知和环绕通知。
        前置通知使用 @Before 注解标注,在目标方法执行之前被调用。
        后置通知使用 @After 注解标注,在切点方法执行之后被调用。
        环绕通知使用了 @Around 注解标注,在切点方法执行前后都可以进行一些额外的处理。(这里就不演示,大家可以自己实现一下)

这些注解里execution表达式就是AOP的切点表达式,指明了目标地址,用来告诉程序哪些方法需要用AOP处理

BookHandel就是目标对象,我们需要对该类的业务使用AOP进行日志记录。

运行结果:

这样就实现一个简单的日志管理。

四.AOP的实现原理

AOP在spring和综合是通过代理实现的。在AOP编程中,如果一个类被标记为目标对象,则spring的IOC容器会为该类生成一个代理对象,在获取此目标对象的时候,返回的式代理对象。在调用代理对象的方法时,会依次执行目标对象的前置通知,目标方法,目标方法的后置通知。

springAOP实现代理的方式有两种:

1.JDK动态代理:系统默认会采用这种代理方式,但目标对象必须是实现一个或者多个接口。(原因这里不说明,感兴趣的看一看这篇博客)【深度思考】聊聊JDK动态代理原理_jdk代理-CSDN博客

示例:

接口staff

public interface staff {
    void work();
}

coder类:



public class coder implements staff{
    @Override
    public void work() {
        System.out.println("写代码");
    }
}
AttendanceInvocationHandler类
package com.example.aop;
import org.springframework.cglib.proxy.InvocationHandler;
import java.lang.reflect.Method;
public class AttendanceInvocationHandler implements InvocationHandler {
    private Object target;

    public  AttendanceInvocationHandler(Object target){
        this.target=target;
    }
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("上班打卡");
        Object invoke = method.invoke(target, objects);
        System.out.println("下班打卡");
        return invoke;
    }
}

 

测试类:

import org.springframework.cglib.proxy.Proxy;
public class Text {
    public static void main(String[] args) {
        coder coder = new coder();
        //获得代理对象
        Object proxyInstance = Proxy.newProxyInstance(coder.class.getClassLoader(), coder.class.getInterfaces(),
                new AttendanceInvocationHandler(coder));
        staff staff=(staff) proxyInstance;
        staff.work();
    }
}

 运行结果:

2.CGLIB动态代理:如果目标对象没有实现接口,Spring AOP 就会使用 CGLIB(Code Generation Library)来为目标对象创建代理。CGLIB 使用字节码生成技术,在运行时生成目标对象的子类,并重写其中的方法来织入切面逻辑。

示例:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class Text1 {
    public static void main(String[] args) {
        coder coder = new coder();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(coder.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("上班打卡");
                Object invoke = method.invoke(coder, objects);
                System.out.println("下班打卡");
                return invoke;
            }
        });
        coder o = (coder)enhancer.create();
        o.work();
    }
}

运行结果跟上面一样。

Spring AOP(Aspect-Oriented Programming)是一种基于面向切面编程的技术,它通过将一个应用程序分解成许多独立的部分,从而提高了应用程序的模块化程度,同时也提高了代码的可重用性和可维护性。 Spring AOP 是在运行时对程序进行修改的,它不需要重新编译源代码,因此使得代码的维护和修改更加方便。Spring AOP 原理主要分为以下几个方面: 1. 切面(Aspect):切面是一个类,其中包含了一组相关的Advice和其他相关的代码,用于在目标对象的方法执行前、执行后或者抛出异常时执行相应的操作。 2. 连接点(Join point):连接点是指在应用程序的执行过程中,可以被切面拦截的点,比如方法调用、异常抛出、属性赋值等。 3. 通知(Advice):通知是指在连接点处执行的代码,有多种类型的通知,包括前置通知(Before advice)、后置通知(After advice)、返回通知(After returning advice)、异常通知(After throwing advice)和环绕通知(Around advice)。 4. 切入点(Pointcut):切入点是一个表达式,用于定义哪些连接点会被切面拦截。 5. 代理(Proxy):代理是指在目标对象和切面之间创建的对象,它可以拦截目标对象的方法调用,并在方法执行前后执行相应的通知。 Spring AOP 的实现机制主要是通过 JDK 动态代理或者 CGLIB 动态代理来实现的。当目标对象实现了接口时,Spring AOP 使用 JDK 动态代理,否则使用 CGLIB 动态代理。在 JDK 动态代理中,代理对象实现了与目标对象相同的接口,而在 CGLIB 动态代理中,代理对象是目标对象的子类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值