JVM 加载class 文件的原理机制
● JVM 中类的装载是由ClassLoader 和它的子类来实现的,Java ClassLoader是一个重要的Java 运行时系统组件。它负责在运行时查找和装入类文件的类。
集合
● List: 序,按对象进入的顺序保存对象,可重复,允许多个Null元索对象,可以使用lterator取出所有元素,在逐一遍历,还可以使用get(int index)获取指定下表的元索
● Set: 无序,不可重复,最多允许有一个Null元素对象,取元素时只能用lterator接口取得所有元素,在逐一遍历各个元素方式。
● ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问) , 扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素), 使用尾插法并指定初始容量可以极大提升性能、甚至超过linkedList (需要创建大量的node对象)
● LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历,遍历LinkedList必须使用iterator不能使用for循环,因为每次for循环体内通过get()取得某一元素时都需要对list重新进行遍历,性能消耗极大。
另外不要试图使用indexOf等返回元素索引,并利用其进行遍历,使用indexIOf对list进行 了遍历,当结果为空时会遍历整个列表。
● HashMap:线程不安全,HashMap允许Key和Value为null,底层采用数组加链表结构实现.
jdk8开始,链表高度到8并且数组长度超过64的时候,链表会转变成红黑树,元素以内部类Node节点存在.
● HashTable:使用了synchronized修饰,线程安全,不允许null值出现
Spring是一个开源的轻量级的Java EE开发框架.Spring框架的目标是使得Java EE应用程序的开发更加简便,通过使用POJO为基础的编程模型促进良好的编程风格.
Spring框架的核心是Spring容器.容器创建对象,将他们装配在一起,配置他们并管理他们的完整生命周期.Spring使用依赖注入来管理组成应用程序的组件.容器通过读取提供的配置元数据来接收对象进行实例化.
在依赖注入中,您不必创建对象,但必须描述如何创建他们.不是直接在代码中将组件和服务连接在一起,而是描述配置文件中那些组件需要那些服务,然后由IOC容器将他们装配在一起.
public class StupidStudent {
private SmartStudent smartStudent;
public StupidStudent(SmartStudent smartStudent) {
this.smartStudent = smartStudent;
}
public doHomewrok() {
smartStudent.doHomework();
System.out.println("学渣抄作业");
}
}
public class StudentTest {
public static void main(String[] args) {
SmartStudent smartStudent = new SmartStudent();
StupidStudent stupidStudent = new StupidStudent(smartStudent);
stupidStudent.doHomework();
}
}
这种方式就好比学渣从一开始就赖上了一个学霸,并且和这个学霸建立了长期合作关系.
public class StupidStudent {
private SmartStudent smartStudent;
public void setSmartStudent(SmartStudent smartStudent) {
this.smartStudent = smartStudent;
}
public doHomewrok() {
smartStudent.doHomework();
System.out.println("学渣抄作业");
}
}
public class StudentTest {
public static void main(String[] args) {
SmartStudent smartStudent = new SmartStudent();
StupidStudent stupidStudent = new StupidStudent();
stupidStudent.setSmartStudent(smartStudent);
stupidStudent.doHomework();
}
}
这种方式学霸和学渣只是暂时的合作关系,如果学渣赖上了另一个学霸(调用set()方法传入了另一个对象),那么学渣和学霸的合作关系就结束了。
注解注入在Spring中是用的最多的一种方式,就是在java代码中使用注解的方式进行装配,在代码中加入@Resource或者@Autowired.
Autowired是自动注入,自动从spring的上下文找到合适的bean来注入.
Resource用来指定名称注入.
Qualifier和Autowired配合使用,指定bean的名称.(Resource注解传递指定Bean名称相当于Autowired+Qualifier注解)
上面的Autowired和Resource是用来修饰字段,构造函数,或者设置方法,并做注入的。而Service,Controller,Repository,Component则是用来修饰类,标记这些类要生成bean。
总结:构造器注入适用于设置多个属性,任意修改都会创建新的实例;Setter注入适用于设置少量属性,任意更改都不会创建新实例.
基础类型IOC容器,提供了完整的IOC服务支持.默认采用延迟初始化策略(lazy-load).只有当客户端需要访问到容器中某一个受管对象的时候,才会对受管对象进行初始化以及依赖注入操作,所以相对来说,容器启动初期速度较快,所需要的资源有限.
这是BeanFactory的升级版,拥有了BeanFactory的所有支持,ApplicationContext还提供了其他的高级特性,比如事件发布、国际化信息支持等.
ApplicationContext默认初始化全部容器对象(及时加载),需要更多的系统资源,启动时间较长.
bean所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多bean定义和特定于应用程序的配置选项。它们通常以bean标签开头。例如:
您可以通过在相关的类,方法或字段声明上使用注解,将bean配置为组件类本身,而不是使用XML来描述bean装配。默认情况下,Spring容器中未打开注解装配。因此,您需要在使用它之前在Spring配置文件中启用它。例如:
Spring 的 Java配置是通过使用@Bean和@Configuration 来实现。
@Bean注解扮演与元素相同的角色。
@Configuration类允许通过简单地调用同一个类中的其他@Bean方法来定义bean间依赖关系。
@Configuration public class StudentConfig {
@Bean public StudentBean myStudent() {
return new StudentBean();
}
}
以动态非侵入式的方式增强服务的一种编程思想
AOP(Aspect Oriented Programming,面向切面编程),可以说是 OOP(Object Oriented Programing,面向对象编程)的补充和完善。OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,用来模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能,日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如权限管理、异常处理等也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在 OOP 设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而 AOP 技术则恰恰相反,它利用一种称为 “横切” 的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为 “Aspect” ,即切面。所谓“切面”,简单地说,就是将权限、事务、日志、异常等与业务逻辑相对独立的功能抽取封装,便于减少系统的重复代码,降低模块间的耦合度,增加代码的可维护性。AOP 代表的是一个横向的关系,如果说 “对象” 是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向切面编程,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息,然后又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
切面理解:用刀将西瓜分成两瓣,切开的切口就是切面;炒菜、锅与炉子共同来完成炒菜,锅与炉子就是切面。Web 层级设计中,Controller 层、Service 层、Dao 层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。
Tips:可以使用连接点获取执行的类名、方法名和参数名等。
Pointcut(切入点)
是在连接点的基础上来定义切入点。比如在一个类中,有 15 个方法,那么就会有几十个连接点,但只想让其中几个方法的前后或抛出异常时干点什么,那么就用切入点来定义这几个方法,让切入点来筛选连接点。
Aspect(切面)
是通知(Advice)和切入点(Pointcut)的结合,通知(Advice)说明了干什么和什么时候(通过@Before、@Around、@After、@AfterReturning、@AfterThrowing来定义执行时间点)干,切入点(Pointcut)说明了在哪(指定方法)干,这就是一个完整的切面定义。
AOP 代理
AOP Proxy:AOP 框架创建的对象,代理就是目标对象的加强。AOP 巧妙的例用动态代理优雅的解决了 OOP 力所不及的问题。Spring 中的 AOP 代理可以是 jdk 动态代理,也可以是 cglib 动态代理。前者基于接口,后者基于子类。
Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这不要根据具体情况来定。
spring对单例的实现: spring中的单例模式完成了后半句话,即提供了全局的访问点BeanFactory.但没有从构造器级别去控制单例,这是因为spring管理的是任意的java对象。
Spring定义了一个适配接口,使得每一种Controller有一 种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller时,只需要增加一个适配器类就完成了SpringMVC的扩展了。
1)用户发送请求至前端控制器DispatcherServlet.
2) DispatcherServlet 收到请求调用HandlerMapping处理器映射器。
3)处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器及处理器拦截器(如果有则生
成)-并返回给DispatcherServlet。
4) DispatcherServlet 调用HandlerAdapter处理器适配器。
5) HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)
6) Controller 执行完成返回ModelAndView。
7) HandlerAdapter 将controller执行结果ModelAndView返回给DispatcherServlet。8) DispatcherServlet
将ModelAndView传给ViewReslover视图解析器。
9) ViewReslover 解析后返回具体View。
10) DispatcherServlet 根据View进行渲染视图(即将模型数据填充至视图中)。
11) DispatcherServlet 响应用户。
@Import + @Configuration + Spring spi
自动配置类由各个starter提供,使用@Configuration + @Bean定义配置类,放到META-INF/spring.factories下使用Spring spi扫描META-INF/spring.factories下的配置类
使用@Import导入自动配置类
1、基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理; 提供XML标签,支持编写动态SQL语询,并可重用。
2、与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
3、很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要DBC支持的数据库MyBatis都支持)。
4、能够与Spring很好的集成;
5、提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
缺点:
1、SQL语句的编写.工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语询的功底有一定要求。
2、SQL 语句依赖于数据库,导致数据库移植性差 ,不能随意更换数据库。
hibernate简化了dao层,使用者不需要考虑sql语句的编写与执行以及结果映射,将着重点放在业务逻辑上,而mybatis需要使用者手写sql语句以及resultMap,所以hibernate开发速度要比mybatis快。
但是hibernate门槛要比mybatis高,两者之间做选择时要根据项目实际需求作为标准,如:项目绝大多数是简单的数据操作,比如增删改查,没有太多的复杂sql语句,这时选择hibernate用于dao工具会更简便、效率更高一些;反之,如果项目有很多复杂的sql语句,则适合选择mybatis,因为mybatis可以进行更为细致的sql优化,可以减少查询字段从而提高效率(因为hibernate会把所有字段都进行处理,效率会稍低)。
MyBatis提供了一级缓存和二级缓存
索引用来快速地寻找那些具有特定值的记录。如果没有索引,-般来说执行查询时遍历整张表。
索弓的原理:就是把无序的数据变成有序的查询
都是B+树的数据结构
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
工作模式