IOC如何在容器中创建对象?
在配置文件被加载的时候,我们的spring管理容器bean已初始化。
在getBean此类对象已被创建,采用无参结构法创建对象。
IOC也可以用参构造器创建对象
1.通过参考构造器下标创建对象: 可以看以看到上面标有0的参数,是不是只有一个,就是有参结构name参数 2.通过参数类型创建对象: 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。 特点: 1.根节点必须是黑色的 2.红节点不能连续,黑节点可以连续 3.对于每个节点,从节点到所有后代叶节点的简单路径含相同数量的黑色节点 插入步骤: 1、搜索 2、创建新节点,插入合适位置 3.调整结构或颜色 AVL结构是否调整取决于每个节点的平衡因素,红黑树结构和颜色调整取决于节点的颜色限制。
B-Tree
1.叶结点深度相同,叶节点指针为空 所有元素不重复 3.节点中的数据索引从左到右增加排列 当前节点中包含的键值存储在每个节点中(Key/Data)指向下一个节点的指针。
查找: 例如,如果我们在上述B树中搜索数据49,过程将如下: 1.将项目49与根节点78进行比较。因为49 <所以移到它的左子树上。 2、从40 <49 <从56开始,遍历40棵右子树。 3、49> 向右移动。比较49。 4.找到匹配项并返回。 插入: 1.遍历B树,找到适当的叶节点,可以在其上插入节点。 2.如果叶节点的含量少于2,如果叶节点的含量少于2,如果叶节点的含量少于2,则m-按升序按升序插入元素。 3.如果叶子节点包含m-一键,请执行以下步骤
- 根据元素的升序插入新元素。
- 将节点分成中间的两个节点。
- 将中值元素推到父节点。
B+Tree
1、非叶子结点不存储数据,只存储索引(冗余),可以存放更多的索引 2、叶子结点包含所有索引字段 3、叶子结点用指针链接,提高区间访问的性能(可以提升范围查找的效率)
Hash
1、对索引的 key 进行一次 hash 计算就可以定位出数据存储的位置 2、很多的时候 hash 索引要比 B+ 树索引更高效 3、仅能满足 “=” , “in” 不支持范围查询
创建索引的方式
1)使用 CREATE INDEX 语句
可以使用专门用于创建索引的 CREATE INDEX 语句在一个已有的表上创建索引,但该语句不能创建主键。
语句格式:
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。
如果当前monitor的进入数为0时,线程就会进入monitor,并且把进入数+1,那么该线程就是monitor的拥有者(owner)。
、如果该线程已经是monitor的拥有者,又重新进入,就会把进入数再次+1。也就是可重入的。
执行monitorexit的线程必须是monitor的拥有者,指令执行后,monitor的进入数减1,如果减1后进入数为0,则该线程会退出monitor。其他被阻塞的线程就可以尝试去获取monitor的所有权、
同步方法原理
有一个标志位。作用就是一旦执行到这个方法时,就会先判断是否有标志位,如果有这个标志位,就会先尝试获取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的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉