Spring全套教学资料
Spring是Java程序员的《葵花宝典》,其中提供的各种大招,能简化我们的开发,大大提升开发效率!目前99%的公司使用了Spring,大家可以去各大招聘网站看一下,Spring算是必备技能,所以一定要掌握。
目录:
部分内容:
Spring源码
- 第一部分 Spring 概述
- 第二部分 核心思想
- 第三部分 手写实现 IoC 和 AOP(自定义Spring框架)
- 第四部分 Spring IOC 高级应用
基础特性
高级特性 - 第五部分 Spring IOC源码深度剖析
设计优雅
设计模式
注意:原则、方法和技巧 - 第六部分 Spring AOP 应用
声明事务控制 - 第七部分 Spring AOP源码深度剖析
必要的笔记、必要的图、通俗易懂的语言化解知识难点
脚手框架:SpringBoot技术
它的目标是简化Spring应用和服务的创建、开发与部署,简化了配置文件,使用嵌入式web服务器,含有诸多开箱即用的微服务功能,可以和spring cloud联合部署。
Spring Boot的核心思想是约定大于配置,应用只需要很少的配置即可,简化了应用开发模式。
- SpringBoot入门
- 配置文件
- 日志
- Web开发
- Docker
- SpringBoot与数据访问
- 启动配置原理
- 自定义starter
微服务架构:Spring Cloud Alibaba
同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
- 微服务架构介绍
- Spring Cloud Alibaba介绍
- 微服务环境搭建
- 服务治理
- 服务容错
- 服务网关
- 链路追踪
- ZipKin集成及数据持久化
- 消息驱动
- 短信服务
- Nacos Confifig—服务配置
- Seata—分布式事务
- Dubbo—rpc通信
Spring MVC
目录:
部分内容:
}
}
上述代码在运行时会提示如下错误
java: 变量 name 未在默认构造器中初始化
修改成下面的方式即可。
public class TCCClass {
private final String name=“name”;
}
- 在构造方法中赋值
public class TCCClass {
private final String name;
public TCCClass(String name){
this.name=name;
}
}
能够在构造方法中赋值的原因是:对于一个普通成员属性赋值时,必须要先通过构造方法实例化该对象。因此作为该属性唯一的访问入口,JVM允许在构造方法中给final
修饰的属性赋值。这个过程并没有违反final
的原则。当然如果被修饰final
关键字的属性已经初始化了值,是无法再使用构造方法重新赋值的。
反射破坏final规则
基于上述final关键字的基本使用描述,可以知道final
修饰的属性是不可变的。
但是,通过反射机制,可以破坏final
的规则,代码如下
public class TCCClass {
private final String name=“name”;
public static void main(String[] args) throws Exception {
TCCClass tcc=new TCCClass();
System.out.println(tcc.name);
Field name=tcc.getClass().getDeclaredField(“name”);
name.setAccessible(true);
name.set(tcc,“mic”);
System.out.println(name.get(tcc));
}
}
打印结果如下:
name
mic
知识点扩展
上述代码理论上来说应该是下面这种写法,因为通过反射修改tcc实例对象中的
name
属性后,应该通过实例对象直接打印出name
的结果。
public static void main(String[] args) throws Exception {
TCCClass tcc=new TCCClass();
System.out.println(tcc.name);
Field name=tcc.getClass().getDeclaredField(“name”);
name.setAccessible(true);
name.set(tcc,“mic”);
System.out.println(tcc.name); //here
}
但是实际输出结果后,发现
tcc.name
打印的结果没有变化?
原因是:JVM在编译时期做的深度优化机制, 就把final类型的String进行了优化, 在编译时期就会把String处理成常量,导致打印结果不会发生变化。
为了避免这种深度优化带来的影响,我们还可以把上述代码修改成下面这种形式
public class TCCClass {
private final String name=(null == null ? "name" : "");
public static void main(String[] args) throws Exception {
TCCClass tcc=new TCCClass();
System.out.println(tcc.name);
Field name=tcc.getClass().getDeclaredField("name");
name.setAccessible(true);
name.set(tcc,"mic");
System.out.println(tcc.name);
}
}
打印结果如下:
name
mic
反射无法修改被final和static同时修饰的变量
把上面的代码修改如下。
public class TCCClass {
private static final String name=(null == null ? “name” : “”);
public static void main(String[] args) throws Exception {
TCCClass tcc=new TCCClass();
System.out.println(tcc.name);
Field name=tcc.getClass().getDeclaredField(“name”);
name.setAccessible(true);
name.set(tcc,“mic”);
System.out.println(tcc.name);
}
}
执行结果,执行之后会报出如下异常, 因为反射无法修改同时被static final修饰的变量:
Exception in thread “main” java.lang.IllegalAccessException: Can not set static final java.lang.String field org.example.cl03.TCCClass.name to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(UnsafeQualifiedStaticObjectFieldAccessorImpl.java:77)
at java.lang.reflect.Field.set(Field.java:764)
at org.example.cl03.TCCClass.main(TCCClass.java:13)
那么被final和static同时修饰的属性,能否被修改呢?答案是可以的!
修改代码如下:
public class TCCClass {
private static final String name=(null == null ? “name” : “”);
public static void main(String[] args) throws Exception {
TCCClass tcc=new TCCClass();
System.out.println(tcc.name);
Field name=tcc.getClass().getDeclaredField(“name”);
name.setAccessible(true);
Field modifiers = name.getClass().getDeclaredField(“modifiers”);
modifiers.setAccessible(true);
modifiers.setInt(name, name.getModifiers() & ~Modifier.FINAL);
name.set(tcc,“mic”);
modifiers.setInt(name, name.getModifiers() & ~Modifier.FINAL);
System.out.println(tcc.name);
}
}
具体思路是,把被修饰了final
关键字的name
属性,通过反射的方式去掉final
关键字,代码实现
Field modifiers = name.getClass().getDeclaredField(“modifiers”);
modifiers.setAccessible(true);
modifiers.setInt(name, name.getModifiers() & ~Modifier.FINAL);
接着通过反射修改name
属性,修改成功后,再使用下面代码把final
关键字加回来
modifiers.setInt(name, name.getModifiers() & ~Modifier.FINAL);
为什么局部内部类和匿名内部类只能访问final变量
在了解这个问题之前,我们先来看下面这段代码
public static void main(String[] args) {
}
public void test(final int b) {
final int a = 10;
new Thread(){
public void run() {
System.out.println(a);
System.out.println(b);
};
}.start();
}
}
这段代码被编译后,会生成两个文件: FinalExample.class和FinalExample$1.class(匿名内部类)
通过反编译来看一下FinalExample$1.class
这个类
class FinalExample$1 extends Thread {
FinalExample$1(FinalExample this$0, int var2, int var3) {
this.this$0 = this$0;
this.val$a = var2;
this.val$b = var3;
}
public void run() {
System.out.println(this.val$a);
System.out.println(this.val$b);
}
}
我们看到匿名内部类FinalExample$1的构造器含有三个参数,一个是指向外部类对象的引用,另外两个是int型变量,很显然,这里是将变量test方法中的形参b
,以及常量a
以参数的形式传进来,对匿名内部类中的拷贝(变量a
和b
的拷贝)进行赋值初始化。
也就是说,在run
方法中访问的变量a
和b
,是局部变量a
和b
的一个副本,为什么这么设计?
在
test
方法中,有可能test
方法执行结束且a
和b
的声明周期也结束了,但是Thread这个匿名内部类可能还未执行完,那么在Thread中的run
方法中继续使用局部变量a
和b
就会有问题。但是又要实现这样的效果,怎么办呢?所以Java采用了复制的手段来解决这个问题。
但是这样一来,还是存在一个问题,就是test
方法中的成员变量与匿名内部类Thread中的成员变量的副本出现数据不一致怎么办?
这样就达不到原本的意图和要求。为了解决这个问题,java编译器就限定必须将变量a
和b
限制为final变量,不允许对变量a
和b
进行更改(对于引用类型的变量,是不允许指向新的对象),这样数据不一致性的问题就得以解决了。
另外,如果我们这么写也是允许的,jvm会隐式给a
和b
增加final
关键字。
public void test(int b) {
int a = 10;
new Thread(){
public void run() {
System.out.println(a);
System.out.println(b);
};
}.start();
}
final防止指令重排
最后
总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习
还有更多学习笔记面试资料也分享如下:
式给a
和b
增加final
关键字。
public void test(int b) {
int a = 10;
new Thread(){
public void run() {
System.out.println(a);
System.out.println(b);
};
}.start();
}
final防止指令重排
最后
总而言之,面试官问来问去,问的那些Redis知识点也就这么多吧,复习的不够到位,知识点掌握不够熟练,所以面试才会卡壳。将这些Redis面试知识解析以及我整理的一些学习笔记分享出来给大家参考学习
还有更多学习笔记面试资料也分享如下:
[外链图片转存中…(img-fLz8S8QH-1715123688623)]