换种眼光看Spring之bean是怎么诞生的(一)
Java的世界里处处存在了对象,有时候换一种眼光往往会给自己带来与之前大不一样的理解。
一个对象的出现离不开字节码,拿classforname来讲,classforname("...") 就像问你 狗 ,在你脑子里立马就出现了狗的样子,这就是狗的类,拉布拉多就出现拉布拉多狗的类,就类似于一个加载的过程,想要得到私有的方法,私有的类,比如拉布拉多和其他种类狗的区别,私有的用setAccessible设置为true,这样就可以调用,这其中加载的过程一眼就看到了父类也会加载进去,这就是类的初始化。
而这里还要说的是classloader是从BootStrapClassLoader开始,到ExtClassLoader再到AppClassLoader,再到自己的ClassLoader。很多人看到这些有的会很明白,同样的也有很多大头的,其实拿我们自身来说,我们要生存,首先我们自己得先活着,这就要求我们有血有肉,各个器官各种完好,BootStrapClassLoader不就是类似于干这事的么,它主要用于加载一些Java自带的核心类,是不能被替换掉的,由jvm内核实现,只有加载了这些最核心的内容,才会有后面classloader的存在机会。
在有了基本的器官之后,作为人,我们要生存还需要一些本能,呼吸,眨眼,条件反射(先天的),这个就类似于ExtClassLoader,其是加载在jre/lib/ext下的jar包,当然,我们也可以把自己的jar放到里面去,通过这个来加载,毕竟我们的好多先天的条件反射也是慢慢进化来的,是不是很形象
作为人,我们可以学习到很多技能,认识很多事物,每个人的所见都不一样,每个人都是一个独立的虚拟机,这里就谈到了AppClassLoader,它加载的是classpath下面的内容,默认情况都由其加载。
当然,凡事总有特殊,用户自定义的classloader要加载的内容不在上面的classpath范围内,怎么加载完全自己去定义,就像你从未见过某一种东西,你怎么去知道那是什么,要不就不打算认识说不知道,要不就给其编个名字安上!
上面说了一些class字节码的加载顺序,然后就是对其进行解析校验,最后是初始化,既然说到了这里,那就提下,初始化的时候会调用Class对象自身的构造函数,这里static块其实是个坑,当多个线程同时访问这个类时,必须等static块执行完,要不会发生阻塞,所以不适合编写大量的业务尤其是i/o逻辑业务
在classloader源码里发现了如下代码:
protected final Class<?> defineClass(String name, byte[] b, int off, int len)
throws ClassFormatError
{
return defineClass(name, b, off, len, null);
}
通过传入byte[]数组就可以动态的加载Class类,这就牵扯到了字节码加强。
终于和上一篇接着了,只要接触过Spring都知道,AOP,动态代理,追根究底都是字节码增强,所以也免不了俗,先说动态代理,看过很多这方面的文章,说说自己的理解,首先,jdk的动态代理,有点类似于专卖店,我拿房地产中介来说可能更好理解一些,一个共同的接口,卖房,房主实现了卖方的接口,房产中介也实现了卖方的接口,然后要有一套卖家卖房的处理流程也就是处理类handler,这个处理类的内部的invoke方法,如下图所示:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
包含了代理对象,代理方法,方法参数对象,方法内部由被代理的对象来实现,其实就是包含了中介,卖房扯的过程,方法里面由卖家来实现
java.lang.reflect.Proxy下的newProxyInstance()方法如下所示
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
} /*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs); /*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
} final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
说白了就是想得到一个代理,就需要卖家的字节码,卖房的接口,和那个处理类handler,jdk动态代理的不好处也是显而易见的,必须实现接口,只能调用接口对应的方法,实例的其他方法无法访问,从这点也启示了我们面向接口编程和多态的用处。
暂时先敲这么多吧,剩下的下篇接着说
换种眼光看Spring之bean是怎么诞生的(一)的更多相关文章
- spring实例化bean三种方式
我看了这篇博文<https://www.cnblogs.com/zhanglei93/p/6221546.html>,以及自己实践总结了关于spring实例化bean对象的3种方式. 一. ...
- 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比
[原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...
- Spring中bean的四种注入方式
一.前言 最近在复习Spring的相关内容,这篇博客就来记录一下Spring为bean的属性注入值的四种方式.这篇博客主要讲解在xml文件中,如何为bean的属性注入值,最后也会简单提一下使用注解 ...
- 如果你每次面试前都要去背一篇Spring中Bean的生命周期,请看完这篇文章
前言 当你准备去复习Spring中Bean的生命周期的时候,这个时候你开始上网找资料,很大概率会看到下面这张图: 先不论这张图上是否全面,但是就说这张图吧,你是不是背了又忘,忘了又背? 究其原因在于, ...
- 面试阿里,字节,美团必看的Spring的Bean管理详解
IOC容器 工厂只负责创建对象,而Spring当然不仅仅是一个对象工厂,其核心是一个对象容器,其具备控制反转的能力,所以也称为IOC容器. 帮助我们存放对象,并且管理对象,包括:创建.销毁.装配,这样 ...
- Spring三 Bean的三种创建方式
创建Bean的三种方式在大多数情况下,Spring容器直接通过new关键字调用构造器来创建Bean实例,而class属性指定Bean实例的实现类,但这不是实例化Bean的唯一方法.实际上,Spring ...
- spring创建bean的三种方式
spring创建bean的三种方式: 1通过构造方法创建bean(最常用) 1.1 spring默认会通过无参构造方法来创建bean,如果xml文件是这样配置,则实体类中必须要有无参构造方法,无参构造 ...
- Spring获取bean的几种方式
工作中需要对一个原本加载属性文件的工具类修改成对数据库的操作当然,ado层已经写好,但是需要从Spring中获取bean,然而,工具类并没有交给Spring来管理,所以需要通过方法获取所需要的bean ...
- Spring实例化Bean三种方法:构造器、静态工厂、实例工厂
Spring中Bean相当于java中的类,可以通过xml文件对bean进行配置和管理. 一.Bean的实例化: 构造器实例化.静态工厂实例化.实例工厂方式实例化. 目录: 构造器实例化: xml配置 ...
随机推荐
- AT&T 和 Intel 汇编语法的主要区别
转自AT&T 和 Intel 汇编语法的主要区别 作为一个爱折腾的大好青年,补番之余还要补一些 Linux 下的基础,比如 GDB 的正确使用方法.但无论是看 gdb 还是 gcc -S 里的 ...
- Java Web 前端高性能优化(二)
一.上文回顾 上回我们主要从图片的合并.压缩等方面介绍前端性能优化问题(详见Java Web 前端高性能优化(一)) 本次我们主要从图像BASE64 编码.GZIP压缩.懒加载与预加载以及 OneAP ...
- Linux中与DNS相关的内容
Linux中与DNS有关的三个东西: 1. 主机名 2. DNS服务器 3. Host文件 Linux中和DNS有关的三个文件: 1. /etc/hostname 2. /etc/resolv.con ...
- asp.net控件(1)Repeater
1. 通过Repeater和数据源创建表格 <AlternatingItemTemplate>属性可以控制单元格交替显示不同的背景颜色 <table width=" sty ...
- Android网络请求心路历程
HTTP请求&响应 既然说从入门级开始就说说Http请求包的结构.一次请求就是向目标服务器发送一串文本.什么样的文本?有下面结构的文本.HTTP请求包结构 例子: 1 2 3 4 5 6 7 ...
- LINUX中的虚拟文件系统结构
我的博客:www.while0.com 以下以2.6.32版本的内核源码为例: 虚拟文件系统与具体文件系统之间是几组操作函数的对应,包括file_operations,dentry_operation ...
- 【HDOJ】1260 Tickets
水DP,不过这道题目的数据好像有问题.24时制可表示范围是0~23,12时制可表示范围应为1~12.也就是说24点(即0点)其实表示为12:00:00am,而中午12:00:00其实表示为12:00: ...
- Oracle系列之权限
涉及到表的处理请参看原表结构与数据 Oracle建表插数据等等 赋予权限:前三个要在管理员权限用户下进行操作 方法1: grant dba to db_user;--赋予用户数据库管理权限 方法2: ...
- 分割函数和根据Id串返回名字
需求:函数传入一个字符串参数 例如 123-456 将这个字符串123-456拆成两个值 123 456,在通过两个值分别查出数据(例如 张三 李四),拼接成 张三-李四 --声明变量 ...
- spilt用法简介
//获取墓位位置 string MWFLMC = "和平区祥和园D组A碑11排"; //得到字符数组 ]; //分割字符数组 sArray1 = MWFLMC.Split(] { ...