美文网首页
SpringAop工作原理

SpringAop工作原理

作者: 起个名忒难 | 来源:发表于2018-05-19 17:41 被阅读166次

概述

Spring的两大特性:

  • AOP
  • IOC

关于IOC我们先放在一边,这篇文章主要聊一下AOP。

AOP(Aspect Orient Programming) 面向切面编程。切面能帮助我们模块化横切关注点。简言之:横切关注点,可以被描述为影响应用多处的功能。例如:日志 ,安全,事务,检查等。

在叙述AOP的实现原理之前,先来看一下如果Spring要实现AOP该做那些配置。使用了注解:

定义接口:

public interface Performance {
    void perform();
}

定义接口实现类:

public class PerformanceImpl implements  Performance {
    public void perform() {
        System.out.println("perform is  perform ");
    }
}

定义切面:

@Aspect  //@Aspect 表明该类并不仅仅是一个pojo还是一个切面
public class Audience {
    //定义可重用的切点
    @Pointcut("execution(* com.spring.io.aspectj.PerformanceImpl.perform(..))")
    public void perform() {

    }

    @Before("perform()") //在目标方法执行之前调用
    public void silenceCellPhone() {
        System.out.println("silence cell phone");

    }
    @Before("perform()") //在目标方法执行之后调用
    public void takeSeats() {
        System.out.println("take seats");

    }
    @AfterReturning("perform()") //目标方法返回后调用
    public void applause() {
        System.out.println(" applause ");

    }

    @AfterThrowing("perform()")  //抛出异常后调用
    public void demandRefund() {
        System.out.println("demand refund");

    }


}

java config 配置:

@Configuration
@EnableAspectJAutoProxy  //启用AspectJ自动代理
public class ConcertConfig {
    //声明Audience 
    @Bean
    public Audience audience() {
        return new Audience();
    }
}

xml配置:

<context:component-scan base-package="com.spring.io"/>
<bean id = "performance" class="com.spring.io.aspectj.PerformanceImpl" />

方法调用:

public static void main( String[] args )
{
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knights.xml");
    Performance bean = context.getBean(Performance.class);
    bean.perform();
    context.close();

//执行结果
//silence cell phone
//take seats
//perform is  perform 
//applause 
}

通过以上代码,便通过Spring实现了一个切面功能。 那么它的工作流程是怎样的呢,我们接下来在进行分析。

AOP实现的关键就在AOP框架自动创建的AOP代理,AOP代理分为:

  • 静态代理:在编译阶段就生成AOP代理类
  • 动态代理:借助JDK动态代理(反射)、CGLIB等在内存“临时”生成AOP代理类

静态代理的代表是AspectJ,动态代理的代表是Spring AOP。关于静态代理本文不再叙述,感兴趣的可以自行研究。

SpringAOP的动态代理有两种方式:

  • JDK动态代理: 通过反射技术生成代理类,必须有接口
  • CGLIB动态代理: 没有接口则采用此种方式,通过继承做动态代理

我们说SpringAop是通过JDK动态代理和CGLIB实现的,那么我们就来写一个程序,模仿一下AOP代理类的生成,在回来看springaop中,spring帮助我们做了哪些事。

定义接口:

public interface Performance {
    void perform();
}

定义接口实现类:

public class PerformanceImpl implements  Performance {
    public void perform() {
        System.out.println("perform is  perform ");
    }
}

定义代理类

public class AduienceAop implements InvocationHandler{
    private Object object; //定义代理对象

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("silence cell phone");
        System.out.println("take seats");
        method.invoke(object, args);
        System.out.println(" applause ");
        return null;
    }
}

方法调用:

public static void main(String[] args) {
        PerformanceImpl performance = new PerformanceImpl();
        AduienceAop aduienceAop = new AduienceAop(performance);
        Performance o = (Performance) Proxy.newProxyInstance(performance.getClass().getClassLoader(), performance.getClass().getInterfaces(), aduienceAop);
        o.perform();
}

//执行结果
//silence cell phone
//take seats
//perform is  perform 
//applause 

通过和上面两次的结果比对,发现程序的执行结果是一样的。 在springaop的配置中,我们没有去深入挖掘它的执行过程,但是在动态代理的执行过程,对我们确是很清晰。首先基于我们实现的手动代理类,我们定义了需要执行的业务逻辑。定义类接口,并实现了它。我们让切面实现了InvocationHandler接口,在invoke()方法中织入了切面需要执行的代码,并通过Proxy.newProxyInstance()方法创建了对象。在没有对原代码产生入侵的情况下,实现了调用,并加入了切面的功能。

由于spring的源码比较复杂,这里简述一下生成的过程:

在SpringAop中有几个重要的类:

  • JdkDynamicAopProxy
    JdkDynamicAopProxy类是final修饰的,实现了AopProxy,InvocationHandler接口。能够返回Proxy,所以当我们使用proxy时,最终执行的还是invoke()方法。 在spring的底层,会把我们定义的各个Adivce分别包裹成一个MethodInterceptor,这些方法按照加入Advised的顺序,构成一个AdivseChain,相当于方法拦截器,依次执行。

所以基于JDK实现的springAOP的动态代理方式的工作原理为:
接口 + 类 + 切入逻辑 ====》 代理类

基于CGLIB实现的springAOP的动态代理方式的工作原理为:
类 + 切入逻辑 === 》 代理类

SpringAOP的特点:

  • Spring默认使用动态代理的方式实现AOP ,当动态代理不可用采用CGLIB实现
  • 只能对方法进行切入,不能对接口,字段,静态代码块进行切入
  • 同类中互相调用方法将不会使用代理类
  • 性能不是最好的

相关文章

  • SpringAop工作原理

    概述 Spring的两大特性: AOP IOC 关于IOC我们先放在一边,这篇文章主要聊一下AOP。 AOP(As...

  • SpringAOP原理分析

    这篇文章讲解AOP很好,深入浅出的感觉。SpringAOP原理分析

  • SpringAOP的原理

    1、当spring容器启动的时候,加载两个bean,对两个bean进行实例化2、当spring容器对配置文件解析到...

  • SpringAOP-原理

    慕课网《 探秘Spring AOP》笔记 笔记代码https://gitee.com/oooh2016/Sprin...

  • SpringAOP实现原理

    1. 概述 SpringAOP(Aspect Orient Programming)是一种设计思想,称为面向切面编...

  • 2018-12-05

    SpringAOP 生成代理对象原理的步骤 singleton 单例: 配置源码执行过程 ProxyFactor...

  • Spring中的Cache

    SpringAOP的完美案例 使用案例 原理解析 EnableCaching @Import用来整合所有在@Con...

  • java设计模式-代理模式(proxy pattern)

    简述 提到代理模式,脑海中第一个想到的就是springAop。日常工作中,我们用springAop来实现统一权限管...

  • Spring AOP的底层原理

    上一篇 << >> 什么是SpringAop Aop面向切面编程,在方法之前和之后实现处理实现原理:底层使用代理设...

  • Spring_AOP_02——实现原理

    本文主要讲实现AOP的 代理模式原理,以及静态代理,动态代理的区别和具体实现。 对SpringAOP的概念和使用,...

网友评论

      本文标题:SpringAop工作原理

      本文链接:https://www.haomeiwen.com/subject/gbsllftx.html