SpringAop工作原理

概述

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实现
  • 只能对方法进行切入,不能对接口,字段,静态代码块进行切入
  • 同类中互相调用方法将不会使用代理类
  • 性能不是最好的
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,408评论 19 139
  • 说明:本文主要内容来自慕课网。配合视频食用口味更佳。主要是顺着已经学习的视频顺序总结一遍,以深化理解和方便日后复习...
    stoneyang94阅读 4,251评论 3 5
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,661评论 1 133
  • “今天不吃晚饭,都饿一顿啊!” 昨天下午下班一进家门,就听见老婆大人这句话。我一愣,问道:“为啥?没米啦?” “网...
    造业的瞎子阅读 1,813评论 0 1
  • 回忆 打开心的一页 注入的目光 在苦苦寻觅 昨天 是否失去了记忆 斑驳陆离一片 满眼的愁丝 凝聚了薄雾 疏忽成了淡...
    雨雪霏霏飞雨阅读 1,157评论 0 1