Spring IOC、AOP原理

JDK中的动态代理

用法:

public class MyProxy {
    public interface IHello{
        void sayHello();
    }
    static class Hello implements IHello{
        public void sayHello() {
            System.out.println("Hello world!!");
        }
    }
    //自定义InvocationHandler
    static  class HWInvocationHandler implements InvocationHandler{
        //目标对象
        private Object target;
        public HWInvocationHandler(Object target){
            this.target = target;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("------插入前置通知代码-------------");
            //执行相应的目标方法
            Object rs = method.invoke(target,args);
            System.out.println("------插入后置处理代码-------------");
            return rs;
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetExc    eption, InstantiationException {
        //生成$Proxy0的class文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        //获取动态代理类
        Class proxyClazz = Proxy.getProxyClass(IHello.class.getClassLoader(),IHello.class);
        //获得代理类的构造函数,并传入参数类型InvocationHandler.class
        Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
        //通过构造函数来创建动态代理对象,将自定义的InvocationHandler实例传入
        IHello iHello = (IHello) constructor.newInstance(new HWInvocationHandler(new Hello()));
        //通过代理对象调用目标方法
        iHello.sayHello();
    }
}

JDK在实现动态代理时,总流程便是先使用接口类生成代理类的class文件(其中包含接口中声明的需要代理的方法及toString、hashCode等三个Object方法),然后在生成代理类时将实现了InvocationHandler接口的逻辑代理类放入构造器中,反射生成Proxy对象,Proxy对象中含有逻辑代理类对象(一个InvocationHandler对象),在调用Proxy的相关方法时,Proxy就会调用逻辑代理对象中的方法,而我们在逻辑代理对象中已经设置了相关代理逻辑,接着等待调用完成就可以了。

$Proxy0.class:

public final class $Proxy0 extends Proxy implements IHello {   //继承了Proxy类和实现IHello接口
    //变量,都是private static Method  XXX
    private static Method m3;  
    private static Method m1;
    private static Method m0;
    private static Method m2;
    //代理类的构造函数,其参数正是是InvocationHandler实例,Proxy.newInstance方法就是通过通过这个构造函数来创建代理实例的
    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    //接口代理方法
    public final void sayHello() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    //以下Object中的三个方法
    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    //对变量进行一些初始化工作
    static {
        try {
            m3 = Class.forName("com.mobin.proxy.IHello").getMethod("sayHello", new Class[0]);
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

参考:https://www.cnblogs.com/MOBIN/p/5597215.html

在根据接口创建代理类的class文件时有许多步骤,首先会进行一些安全的权限检查,接着需要验证我们传入的接口class数组中的接口是否都是由我们传入的类加载器加载的,以及该class对象是否是接口、接口是否重复等等,然后设置代理类的名称(代理类的包路径)等等,最后,生成代理类的字节码文件,如下方法,便在字节码中放入了一个可传入逻辑代理类对象的构造器,以及接口中存在的各种方法,也就是我们需要代理的各方法。此时,代理类对象创建完毕,返回上层源码,我们最终又获取了字节码中的构造器,在newInstance方法中传入了该构造器和需要接收的对象,即我们创建的逻辑代理类对象,此时,代理类对象创建完毕,返回该Proxy。

private byte[] generateClassFile() {
        /addProxyMethod系列方法就是将接口的方法和Object的hashCode,equals,toString方法添加到代理方法容器(proxyMethods),
         其中方法签名作为key,proxyMethod作为value*/
        /*hashCodeMethod方法位于静态代码块中通过Object对象获得,hashCodeMethod=Object.class.getMethod("hashCode",new Class[0]),
         相当于从Object中继承过来了这三个方法equalsMethod,toStringMethod*/    
        this.addProxyMethod(hashCodeMethod, Object.class);   -->
        this.addProxyMethod(equalsMethod, Object.class);
        this.addProxyMethod(toStringMethod, Object.class);
        int var1;
        int var3;
         //获得所有接口中的所有方法,并将方法添加到代理方法中
        for(var1 = 0; var1 < this.interfaces.length; ++var1) {
            Method[] var2 = this.interfaces[var1].getMethods();           
            for(var3 = 0; var3 < var2.length; ++var3) {
                this.addProxyMethod(var2[var3], this.interfaces[var1]);
            }
        }
          
        Iterator var7 = this.proxyMethods.values().iterator();
        List var8;
        while(var7.hasNext()) {
            var8 = (List)var7.next();
            checkReturnTypes(var8);    //验证具有相同方法签名的的方法的返回值类型是否一致,因为不可能有两个方法名相同,参数相同,而返回值却不同的方法
        };
    //接下来就是写代理类文件的步骤了
        Iterator var11
        try {
             //生成代理类的构造函数
            this.methods.add(this.generateConstructor());
            var7 = this.proxyMethods.values().iterator();
            while(var7.hasNext()) {
                var8 = (List)var7.next();
                var11 = var8.iterator();
                while(var11.hasNext()) {
                    ProxyGenerator.ProxyMethod var4 = (ProxyGenerator.ProxyMethod)var11.next();
                    /将代理字段声明为Method,10为ACC_PRIVATE和ACC_STATAIC的与运算,表示该字段的修饰符为private static
                     所以代理类的字段都是private static Method XXX*/
                    this.fields.add(new ProxyGenerator.FieldInfo(var4.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                    //生成代理类的代理方法
                    this.methods.add(var4.generateMethod());
                }
            }
            //为代理类生成静态代码块,对一些字段进行初始化
            this.methods.add(this.generateStaticInitializer());
        } catch (IOException var6) {
            throw new InternalError("unexpected I/O Exception");
        }
       
        if(this.methods.size() > '\uffff') {  //代理方法超过65535将抛出异常
            throw new IllegalArgumentException("method limit exceeded");
        } else if(this.fields.size() > '\uffff') {   //代理类的字段超过65535将抛出异常
            throw new IllegalArgumentException("field limit exceeded");
        } else {
         //这里开始就是一些代理类文件的过程,此过程略过
            this.cp.getClass(dotToSlash(this.className));
            this.cp.getClass("java/lang/reflect/Proxy");
            for(var1 = 0; var1 < this.interfaces.length; ++var1) {
                this.cp.getClass(dotToSlash(this.interfaces[var1].getName()));
            }
            this.cp.setReadOnly();
            ByteArrayOutputStream var9 = new ByteArrayOutputStream();
            DataOutputStream var10 = new DataOutputStream(var9);
            try {
                var10.writeInt(-889275714);
                var10.writeShort(0);
                var10.writeShort(49);
                this.cp.write(var10);
                var10.writeShort(49);
                var10.writeShort(this.cp.getClass(dotToSlash(this.className)));
                var10.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
                var10.writeShort(this.interfaces.length);
                for(var3 = 0; var3 < this.interfaces.length; ++var3) {
                    var10.writeShort(this.cp.getClass(dotToSlash(this.interfaces[var3].getName())));
                }
                var10.writeShort(this.fields.size());
                var11 = this.fields.iterator();
                while(var11.hasNext()) {
                    ProxyGenerator.FieldInfo var12 = (ProxyGenerator.FieldInfo)var11.next();
                    var12.write(var10);
                }
                var10.writeShort(this.methods.size());
                var11 = this.methods.iterator();
                while(var11.hasNext()) {
                    ProxyGenerator.MethodInfo var13 = (ProxyGenerator.MethodInfo)var11.next();
                    var13.write(var10);
                }
                var10.writeShort(0);
                return var9.toByteArray();
            } catch (IOException var5) {
                throw new InternalError("unexpected I/O Exception");
            }
        }
    }

Spring IOC的实现原理

从最广泛的角度上将,spring ioc(控制反转)就是将对象声明周期的掌控权交给Spring框架管理,而不是程序员new对象了,在需要创建对象时,Spring便会将对象注入到当前的引用中,实现对象间的解耦。单例对象会被Spring放在一个单例Bean的缓存器,单例Bean通过beanName作为key保存在这个HashMap中。属性为prototype的Bean没有缓存器。

实例化Bean的流程:

  1. Resourceloader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源;
  2. BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中。(BeanDefinition中包括所有Bean可配置的属性,例如是否单例、是否延迟加载等等,其相当于一个Java可调用版的XML配置文件,在生成Bean时需要访问其中的各种属性);
  3. 容器扫描BeanDefinitionRegistry中的BeanDefinition ,使用Java的反射机制自动识别出Bean工厂后处理器(实现BeanFactoryPostProcessor接口)的Bean ,然后调用这些Bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理。主要完成以下两项工作:
    1)对使用到占位符的元素标签进行解析,得到最终的配置值,这意味对一些半成品式的BearDefinition对象进行加工处理并得到成品的BeanDefinition对象;
    2)对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean (实现java.beans.PropertyEditor接口的Bean ) ,并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry ) ;
  4. Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition ,并调用Instantiationstrategy着手进行Bean实例化的工作;
  5. 在实例化Bean时, Spring容器使用BeanWrapperBean进行封装, BeanWrapper提供了很多以ava反射机制操作Bean的方法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置工作;
  6. 利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean )对已经完成属性设置工作的Bean进行加工,直接装配出一个准备就绪的Bean。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值