spring源码解读-aop

aop是指面向切面编程,ProxyFactoryBean是spring aop的底层实现与源头,为什么这么说呢?首先我们看一段配置:

1、target是目标对象,需要对其进行切面增强

2、proxyInterfaces是指代理对象所实现的接口

3、interceptorNames:是指通知器(Advisor)列表,通知器中包含了通知advice与切点pointcut

概括一下,ProxyFactoryBean的作用是:

针对目标对象来创建代理对象,将对目标对象方法的调用转到对相应代理对象方法的调用,并且可以在代理对象方法调用前后执行与之匹配的各个通知器中定义好的方法

spring通过两种方式来创建目标代理对象:

1、JDK动态代理

2、CGLIB

在spring中这两种代理方式都实现了AopProxy接口去,如下图所示:

spring中AopProxyFactory是一个接口,接口中只有一个方法createAopProxy,这个接口是有一个实现类DefaultAopProxyFactory,用来创建AopProxy对象,如下图所示:

下面我们比较并实现以下两种代理方式:

首先明确以下我们常用的代理模式有什么问题,在我们经常使用的代理模式中,真实对象必须是事先存在的,并将其作为代理对象的内部属性,在使用时,一个真实角色必须对应一个dialing角色,如果大量使用会导致类的急剧膨胀,java的动态代理类就可以解决这个问题。

JDK动态代理

java动态代理类位于java.lang.reflect包下,一般主要涉及到两个类:

1、Interface InvocationHandler:该接口中只定义了一个方法

 public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

第一个参数proxy是指代理类,method是被代理的方法,args为该方法的参数数组

2、Proxy:该类为动态代理类,其主要方法如下

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException

该方法返回代理类的一个实例,返回后的代理类可以被当作代理类使用

JDK动态代理实现步骤:

1、创建一个实现接口InvocationHandler的类(DynamicSubject),它必须实现invoke方法

public class DynamicSubject implements InvocationHandler {

    private Object sub;

    public DynamicSubject(Object sub) {
        this.sub = sub;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("before calling:" + method);
        method.invoke(sub, args);
        System.out.println(args == null);
        System.out.println("after calling:" + method);
        return null;
    }
}

2、创建被代理的类(RealSubject)以及接口(Subject)

public interface Subject {
    public void request();
}
public class RealSubject implements Subject {

    public void request() {
        System.out.println("from real subject");
    }
}

3、通过Proxy的静态方法newProxyInstance创建一个代理

public class Client {

    public static void main(String[] args) {

        RealSubject realSubject = new RealSubject();
        InvocationHandler handler = new DynamicSubject(realSubject);
        Class<?> classType = handler.getClass();
        Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), realSubject.getClass().getInterfaces(), handler);
        subject.request();
        System.out.println(subject.getClass());
    }
}

如果目标类并未实现接口,那么Spring就会使用CGLIB库为其创建代理,如下demo运用了CGLIB实现代理

1、创建被代理类Person

public class Person {

    public void study() {
        System.out.println("study");
    }
}

2、创建CglibProxy实现代理

public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        Object object = enhancer.create();
        return object;
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println(o.getClass().getName() + "." + method.getName());

        //执行父类对应方法
        final Object result = methodProxy.invokeSuper(o, objects);

        System.out.println("执行结束");

        return result;
    }

    public static void main(String[] args) {

        CglibProxy proxy = new CglibProxy();
        Person person = (Person) proxy.getProxy(Person.class);
        System.out.println(person.getClass().getName());
        person.study();

    }
}

下面我们来比较一下,两种代理方法的区别

1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类

2、CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法

3、在spring中如果bean实现了接口spring用JDK动态代理,如果bean没有实现接口,spring使用CGLIB实现代理

4、CGLIb不能对声明为final的方法进行dialing,因为CGLib原理是动态生成被代理类的子类

5、JDK动态代理通过反射的newInstance方法产生代理类的对象

原文地址:https://www.cnblogs.com/sbrn/p/9260688.html

时间: 2024-10-23 02:53:28

spring源码解读-aop的相关文章

Spring源码解读之XmlBeanFactory

首先感谢<Spring源码深度解析>郝佳.接下来的Spring源码解读系列,都是读了郝佳的书后的观后感.再次感谢他,带我走进了源码的世界. BeanFactory factory= new XmlBeanFactory (new ClassPathResource("D:\\Project\\Eclipse\\Spring_Maven\\src\\main\\resources\\spring_beans.xml" )); new ClassPathResource(Str

spring 源码解读与设计详解:2 BeanFactory

在spring的官网中我们看到,spring的产品已经发展的非常壮大,然而很多产品对于很多公司来讲用的非常少,甚至用不到.因此本系列的源码解读也不会涉及全部的spring的产品.而是只对spring的核心功能IoC和AOP进行解释. 所谓源码解读,解读的是什么?实际上源码解读读的更多的是源码的注释,因为一个类的作用.一个接口或者一个方法的作用,我们往往是要根据注释才知道,这也是为什么在代码规范中,注释是一个非常重要的模块的原因. 参考: Spring源码分析--BeanFactory体系之接口详

Spring源码解读之核心容器上节

Spring架构图 说明 Spring的流行程度就不用我来说了,相信大家如果使用JAVA开发就一定知道它.写这篇文章的初衷在于:1.了解Spring底层实现原理,提升对Spring的认识与理解.2.学习优秀框架编程实现,学习优秀的设计模式.3.使用Spring三年多,对于底层细节希望知道更多,便于求职. 对于Spring整个架构是很庞大的,很难一下看完和思考完,所以我会从Core Container进行切入,一步一步往上走,从而解开Spring神秘的底层面纱.同时对Spring的IOC\AOP\

Spring源码解读之BeanFactoryPostProcessor的处理

前言 前段时间旁听了某课堂两节Spring源码解析课,刚好最近自己又在重新学习中,便在这里记录一下学习所得.我之前写过一篇博文,是介绍BeanFactoryPostProcessor跟BeanPostProcessor是如何发挥作用的,当时觉得讲的还行,但是现在看来,太粗劣了,很多地方没涉及到,而且重点都被我忽略了,简直就是蠢得不行.现在就用这篇文章弥补一下前文中对BeanFactoryPostProcessor的讲解,争取把重点讲到,至于BeanPostProcessor,由于涉及到的东西太多

spring 源码解读与设计详解:3 FactoryBean

上一篇文章讲到BeanFactory,BeanFactory是实现spring IOC原理实现的根接口,而本篇所讲的FactoryBean则是AOP原理实现的重要接口. 1. 先看FactoryBean的源码: public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); } 2. 下面简单讲一下FactoryBea

spring源码之AOP下篇

前言 上篇介绍了一些AOP的基础知识,本篇来说一下spring aop的源码分析.初读AOP时,茫然的是不知道从哪里开始,可能是当初对IOC的理解不够深刻.后面发现其实AOP的入口和IOC一样,也是从两个方法开始.一个是AbstractApplicationContext的fresh方法调用obtainFreshBeanFactory方法去读取配置文件进行初始化操作,另一个就是我的getBean方法了. 概述 在读IOC的时候,我们知道IOC分为两个过程:初始化和依赖注入,那么AOP就是在这两种

spring源码解读之 JdbcTemplate源码

在Spring中,JdbcTemplate是经常被使用的类来帮助用户程序操作数据库,在JdbcTemplate为用户程序提供了许多便利的数据库操作方法,比如查询,更新等,而且在Spring中,有许多类似 JdbcTemplate的模板,比如HibernateTemplate等等 - 看来这是Rod.Johnson的惯用手法, 所谓模板板式,就是在父类中定义算法的主要流程,而把一些个性化的步骤延迟到子类中去实现,父类始终控制着整个流程的主动权,子类只是辅助父类实现某些可定制的步骤. 我们用代码来说

Spring 源码解读 推荐流程

Spring源代码解析(一):IOC容器:http://www.javaeye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.javaeye.com/topic/86594 Spring源代码解析(三):Spring JDBC:http://www.javaeye.com/topic/87034 Spring源代码解析(四):Spring MVC:http://www.javaeye.com/topic/87692 Sprin

Spring源码分析——AOP实现(2)

文章深入讲解了Spring中AOP的实现机制和原理以及使用 AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强:而动态代理则在运行时借助于 JDK 动