spring简介
spring 名词解释 Bean Bean最初是为定义可重用的组件而生. Bean 传统Java Bean EJB Enterprise Java Beans 企业javabeans POJO (Plain Old Java Object) 易用的老的Java类,简单洁净Java对象 DI (Dependency injection) 依赖注入 使用对象或者类时,需要其他对象或者类的协助.一般做法为对象内部直接创建所需对象的实例. 这样使得对象和对象之间耦合紧密. 在对象内部获取一个依赖对象的接口,在使用此对象时,使用其他方式将此对象依赖的对象注入到此对象中. 这样此对象就不知道它依赖的具体实现,降低耦合. AOP 面向切面编程 将业务逻辑从应用服务(监控,事务管理,日志等)中分离出来,实现高内聚. Spring Spring容器,包含并管理应用对象的生命周期和配置 Application Context 上下文 ORM (Object Relational Mapping) JMX 管理扩展 JCA 连接器API MVC (Model View Controller) JMS...
事务管理
Spring框架为Java应用程序提供了强大的事务管理能力,允许开发人员轻松地管理数据库事务,确保数据的一致性和完整性。Spring事务管理支持两种主要模式:编程式事务管理和声明式事务管理。 编程式事务管理(Programmatic Transaction Management) 在编程式事务管理中,开发人员在代码层面显式地管理事务的开启、提交和回滚。Spring提供了PlatformTransactionManager接口来实现这一功能,开发人员通过获取事务管理器的实例,手动调用begin、commit、rollback等方法来控制事务边界。 12345678910111213141516171819@Autowiredprivate PlatformTransactionManager transactionManager;public void someTransactionalMethod() { TransactionDefinition def = new DefaultTransactionDefinition(); ...
面向切面编程AOP
面向切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,它允许程序员对横切关注点(cross-cutting concern)进行模块化的管理。所谓横切关注点,是指那些跨越多个对象或类,与业务逻辑本身无关,但却影响整个系统的行为或性能的共同需求,例如日志记录、权限控制、事务管理、性能监控等。 在传统的面向对象编程(Object-Oriented Programming,OOP)中,这些横切关注点通常分散在各个业务逻辑类的方法中,导致代码重复和耦合度增加。而AOP通过引入“切面”(Aspect)的概念,将这些横切关注点从主业务逻辑中分离出来,单独编写并编织(weave)到主业务流程中,从而实现模块化和解耦。 AOP的核心概念包括: 切面(Aspect): 切面是关注点的模块化表示,它包含通知(advice)、连接点(join point)和切入点(pointcut)的定义。 连接点(Join Point): 连接点是程序执行过程中明确的点,比如方法调用、异常抛出、字段修改等。在Spring...
ArrayList中为什么子列表和原始列表会互相影响,如何避免这种影响
在 Java 中,ArrayList.subList()方法返回的子列表并不是一个独立的副本,而是一个视图(view),它指向原始列表中的某个范围。这意味着对子列表的操作实际上会直接反映到原始列表上,因为它们共享相同的底层数据结构。 例如,在给出的代码片段中: 1234List<Integer> integerList = new ArrayList<>();// ... 添加元素 ...List<Integer> subList = integerList.subList(0, 2);subList.set(0, 10); // 这将改变integerList的第一个元素 当调用subList.set(0, 10)时,虽然操作的是子列表,但实际上是更改了原始列表integerList在对应索引位置上的值。 为了避免这种影响,如果你需要对列表的部分内容进行修改而不影响原始列表,可以创建子列表的一个深拷贝(deep copy)而不是使用视图。例如,你可以使用ArrayList的构造函数来复制子列表: 12List<Integer>...
ArrayList扩容原理
Java 中ArrayList的扩容原理是在其内部数组无法容纳更多元素时,会创建一个新的更大的数组,并将原有数组中的所有元素复制到新数组中。具体过程如下: 初始容量与默认容量: ArrayList在初始化时不指定大小的情况下,默认容量为 10(即DEFAULT_CAPACITY = 10)。 当使用无参构造函数创建一个空ArrayList时,它会初始化一个空数组引用。 添加元素与自动扩容: 当通过add()方法添加元素,且当前存储元素的实际数量(size)等于当前数组的容量时,需要进行扩容操作。 扩容机制通常是将现有容量翻倍,也就是新的容量为原来的两倍加上一定的增长量(通常就是原容量)。扩容计算公式可以是:newCapacity = oldCapacity + (oldCapacity >> 1) 或者 newCapacity = oldCapacity * 1.5 + 1(取决于不同的 Java...
HashMap,TreeMap,LinkedHashMap的区别
Java 中的HashMap, TreeMap, 和 LinkedHashMap 都是实现 java.util.Map 接口的不同类,它们的主要区别在于数据存储结构、排序特性以及迭代顺序。以下是每个类的特点和使用场景: HashMap: 实现原理:基于哈希表(数组+链表或数组+链表+红黑树),通过 key 的 hashCode 值进行散列,并且当发生哈希冲突时采用链表或红黑树来解决冲突。 特点: 无序性:插入元素时没有特定的顺序,遍历结果不保证有序。 性能:查找、添加和删除操作的时间复杂度在平均情况下为 O(1)。 键值唯一:不允许有重复的键,但值可以重复。 线程安全性:非线程安全,在并发环境下需使用 Collections.synchronizedMap() 或 ConcurrentHashMap 来确保线程安全。 TreeMap: 实现原理:基于红黑树(自平衡二叉查找树)实现,自动对键进行排序。 特点: 有序性:根据键的自然顺序(对于实现了 Comparable...
HashMap保证线程安全的方法
在Java中,HashMap类本身并不是线程安全的。这意味着如果多个线程同时读写一个HashMap实例,可能会导致数据不一致或死锁等问题。为了保证线程安全,有以下几种方法可以实现: 使用 java.util.concurrent.ConcurrentHashMap ConcurrentHashMap 是专门为并发环境设计的线程安全的哈希表。它通过分段锁(Segment)机制来实现更高的并发性能,允许多个线程在同一时间对不同部分的数据进行操作。 使用 Collections.synchronizedMap() 包装 可以使用 Collections.synchronizedMap() 方法将一个普通的 HashMap 封装成线程安全的 Map 对象。这样得到的包装对象,在其上的所有操作都会被同步,从而保证线程安全。但请注意,即使进行了同步,迭代时也必须手动加锁,否则可能遇到并发修改异常。 使用 synchronized 关键字同步方法 在自定义类中,可以为 put, get, remove 等方法添加 synchronized...
HashMap其他注意事项
HashMap如果使用对象最为key,要注意什么?(难度:★★ 频率:★) 重写hashCode和equals。 对象比较为什么重写hashCode和equals?(难度:★★ 频率:★) 重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用; a: Map、Set等集合类型存放的对象必须是唯一的; b: 集合类判断两个对象是否相等,是先判断HashCode是否相等,如果HashCode返回TRUE,还要再判断equals返回值是否ture,只有两者都返回ture,才认为该两个对象是相等的。
HashMap扩容的原理
Java中的HashMap在内部使用一个动态可调整容量的数组来存储元素,每个数组元素称为桶(bucket),桶中存放的是键值对对象(Node、TreeNode,在JDK1.8中是链表或红黑树)。当向HashMap中添加新的键值对时,会根据键的哈希码计算出对应的桶位置。随着元素数量的增加,如果继续添加元素导致负载因子(load factor)规定的阈值被超过,则会触发扩容操作。 扩容原理如下: 扩容时机: 当HashMap中的元素个数(size)超过当前容量(capacity)与加载因子(默认为0.75)的乘积时,即 size > capacity *...
Java中的static的用法
使用位置包括:修饰成员属性,修饰成员方法,修饰代码块,修饰内部类,静态导包。 修饰成员属性 给属性加了static关键字之后,对象就不再拥有该属性了,该属性会由类去管理,即多个对象只对应一个属性。 使用场景 一般用于定义一些常量。 1234567891011package com.example.a;class Test{ public static String NAME = "Tony";}public class Demo { public static void main(String[] args) { System.out.println(Test.NAME); }} 执行结果 1Tony 修饰成员方法 方法本来就是存放在类的定义当中的。static修饰成员方法的作用是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗。 示例: 12345678910111213package...