IOC容器里面是如何创造对象的
在配置文件被加载的时候,我们的spring容器中管理的bean就已经被初始化了。
在getBean的时候,这个类的对象就已经被创建了,使用的就是无参构造方法创建对象的。
IOC也可以用有参构造器来创建对象
1、用下标的方式来通过有参构造器创建对象:
可以看到上述下标为0的参数,是不是就只有一个啊,就是有参构造中的name参数
2、用参数的类型的方式来通过有参构造器创建对象:
3、直接通过参数的名称的方式来通过有参构造器创建对象
以上就是spring容器的IOC理念,创建对象的所有方式,一种默认的无参构造器创建,3种有参构造器的创建方式
Spring AOP的实现
Spring AOP机制是由代理模式实现的。
代理模式分为静态代理和动态代理。
静态代理
AspectJ(编译时增强)使用的是静态代理。静态代理指的是AOP框架在编译阶段生成AOP的代理类,它会在编译阶段将AspectJ移植到java字节码中,运行的时候就是增强后的AOP对象。
AspectJ实现方式上是依赖于特殊的AJC编译器。它并非是Spring AOP框架的一部分,而是Spring AOP框架使用了Aspect的Annotation(注解),用来定义切面、切点等功能。
角色分析
抽象角色:一般使用接口或者抽象类解决
真实角色:被代理的角色
代理角色:用来代理真实角色的。代理真实角色后一般会做一些附属操作
客户:调用代理对象的人
动态代理
动态代理的底层其实就是反射机制
- 动态代理角色和静态代理一样
- 动态代理的代理类是动态生成的,不是自己直接写好的
- 动态代理分为两类:基于接口的动态代理(JDK动态代理),基于类的动态代理(CGLIB动态代理)
自动生成代理类通用结构
核心:实现InvocationHandler接口,使用Proxy.newProxyInstance()方法生成代理类
调用上述方法实现动态代理
SpringAOP使用的是动态代理。所谓动态代理指的是AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象就包含了目标对象的所有方法,并且在特定的切点做了增强处理,并回调原对象的方法。底层采用的是JDK/CGLIB动态代理。
Spring AOP里面的几个名词的概念
1)连接点(Join point):指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。
2)切面(Aspect):被抽取出来的公共模块,可以用来会横切多个对象。Aspect切面可以看成 Pointcut切点 和 Advice通知 的结合,一个切面可以由多个切点和通知组成。
3)切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。
4)通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。通知有各种类型,包括Around、Before、After、After returning、After throwing。
5)目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。
6)织入(Weaving):通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。
7)引入(Introduction):添加额外的方法或者字段到被通知的类。Spring允许引入新的接口(以及对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。
Spring容器的启动流程
1、初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中
2、将配置类的BeanDefinition注册到容器中
3、调用refresh()方法刷新容器
初始化:
spring容器的初始化时,通过this()调用了无参构造函数,主要做了以下三个事情:
(1)实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
(2)实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
(3)实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象
Spring框架中的Bean是线程安全的么?如果线程不安全,那么如何处理?
Spring容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体情况还是要结合Bean的作用域来讨论。
(1)对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。
(2)对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。
解决办法
1、作用域由“singleton”改为“prototype”。
2、采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。
- ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。
索引的数据结构
二叉树
二叉树(binary tree)是指树中节点的度不大于 2 的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树
特点:
1、父节点下面有两个子节点。
2、右边节点的数据大于左边节点的数据。
红黑树
红黑树是一种特定类型的二叉树,它的左右子树高差有可能大于 1。
特点:
1、根节点必须是黑色的
2、红色节点不可连续,黑色节点可连续
3、对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
插入步骤:
1、搜索
2、创建新节点,插入合适位置
3、调整结构或调整颜色
AVL根据每个节点平衡因子来决定是否进行结构调整,而红黑树通过节点颜色限制来进行结构和颜色调整。
B-Tree
1、叶子结点具有相同的深度,叶节点的指针为空
2、所有元素不重复
3、节点中的数据索引从左到右边递增排列
其中每个节点中存放当前节点包含的键值(Key/Data)和指向下一个节点的指针。
查找:
例如,如果我们在上述B树中搜索数据49。该过程将如下所示:
1、将项目49与根节点78进行比较。由于49 <78,因此移至其左子树。
2、从40 <49 <56开始,遍历40的右子树。
3、49> 45,向右移动。比较49。
4、找到匹配项,返回。
插入:
1、遍历B树,以找到可以在其上插入节点的适当叶节点。
2、如果叶节点包含少于m-1个键,则按升序插入元素。
3、如果叶子节点包含m-1个键,则请执行以下步骤
- 按元素的升序插入新元素。
- 将节点拆分为中间的两个节点。
- 将中值元素推到其父节点。
B+Tree
1、非叶子结点不存储数据,只存储索引(冗余),可以存放更多的索引
2、叶子结点包含所有索引字段
3、叶子结点用指针链接,提高区间访问的性能(可以提升范围查找的效率)
Hash
1、对索引的 key 进行一次 hash 计算就可以定位出数据存储的位置
2、很多的时候 hash 索引要比 B+ 树索引更高效
3、仅能满足 “=” , “in” 不支持范围查询
创建索引的方式
1)使用 CREATE INDEX 语句
可以使用专门用于创建索引的 CREATE INDEX 语句在一个已有的表上创建索引,但该语句不能创建主键。
语句格式:CREATE <索引名> ON <表名> (<列名> [<长度>] [ ASC | DESC])
2使用 CREATE TABLE 语句
索引也可以在创建表(CREATE TABLE)的同时创建。
类的加载顺序、类加载器
主要包含加载、验证、准备、解析、初始化、使用、卸载七个方面
一、加载
在加载阶段,虚拟机主要完成三件事:
1.通过一个类的全限定名来获取定义此类的二进制字节流。
2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。
3.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区域数据的访问入口
二、验证
验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个java.lang.VerifyError异常或其子类异常。验证过程分为四个阶段:
1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。
2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。
3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。
4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。
三、准备
准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。对已非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值:
pirvate static int size = 12;
那么在这个阶段,size的值为0,而不是12。 final修饰的类变量将会赋值成真实的值。
四、解析
解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。
五、初始化
在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。这些资源有static{}块,构造函数,父类的初始化等。
至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。
类加载器
1、Bootstrap Classloader : 启动类加载器,用来加载 %JAVA_HOME%/jre/lib 下的, 如 rt.jar中的class文件 或者 xbootclasspath选项指定的jar包
2、Extension Classloader : 扩展类加载器 , 用来加载 %JAVA_HOME%/jre/ext 中的class文件 或者 -Djava.ext.dirs指定目录下的jar包
3、 Application Classloader : 应用类加载器 , 用来加载classpath下的class文件
4、Custom Classloader : 用户自定义类加载器,用来加载自定义内容.此加载器需要用户自己继承Classloader类
synchronized
1.Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。
2.Synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。
3.对于类锁synchronized static,是通过该类直接调用加类锁的方法,而对象锁是创建对象调用加对象锁的方法,两者访问是不冲突的,对于同一类型锁锁住的方法,同一对象是无法同时访问的.
synchronized的使用方式
1.修饰实例方法:相当于对当前实例对象this加锁,this作为对象监视器
public synchronized void method(){
// 代码
}
2.修饰静态方法:相当于对当前类的Class对象加锁,当前类的Class对象作为对象监视器
public static synchronized void method(){
// 代码
}
3.修饰代码块:对给定对象加锁,括号括起来的对象就是对象监视器
public void test(){
SynchronizedTest test = new SynchronizedTest();
synchronized (test){
System.out.println("hello world");
}
}
synchronized同步代码块原理分析
同步代码块原理
JVM会在字节码层面给方法块入口处加monitorenter,出口处添加monitorexit标识,一般出口有两个,正常出口和异常出口,所以一般有1个monitorenter对应2个monitorexit。
1、monitorenter: 如果当前monitor的进入数为0时,线程就会进入monitor,并且把进入数+1,那么该线程就是monitor的拥有者(owner)。
2、如果该线程已经是monitor的拥有者,又重新进入,就会把进入数再次+1。也就是可重入的。
3、monitorexit: 执行monitorexit的线程必须是monitor的拥有者,指令执行后,monitor的进入数减1,如果减1后进入数为0,则该线程会退出monitor。其他被阻塞的线程就可以尝试去获取monitor的所有权、
同步方法原理
有一个标志位ACC_SYNCHRONIZED。作用就是一旦执行到这个方法时,就会先判断是否有标志位,如果有这个标志位,就会先尝试获取monitor,获取成功才能执行方法,方法执行完成后再释放monitor。在方法执行期间,其他线程都无法获取同一个monitor。归根结底还是对monitor对象的争夺。
currenthashmap集合
主要就是为了应对hashmap在并发环境下不安全而诞生的,ConcurrentHashMap的设计与实现非常精巧,大量的利用了volatile,final,CAS等lock-free技术来减少锁竞争对于性能的影响。
多线程任务超时的处理机制
https://blog.csdn.net/weixin_45151960/article/details/124701479?spm=1001.2014.3001.5501
mapper.xml文件实现继承的方式
https://blog.csdn.net/weixin_45151960/article/details/124701514
sql连接查询时,on和where后面的条件哪个先执行
例如:
select * from student s left join user u on s.user_id = u.student_id where s.student_id = 1;
说明:
1、on 后面添加的是关联条件, where 添加的是添加查询条件,
2、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录
3、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉