Skip to content

Commit 5ab0f3a

Browse files
committed
Update Java Notes
1 parent f1a33d4 commit 5ab0f3a

File tree

3 files changed

+135
-47
lines changed

3 files changed

+135
-47
lines changed

Frame.md

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8282,7 +8282,7 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
82828282
* **AOP,跳转注解**,`AbstractAutoProxyCreatorwrapIfNecessary -> creatProxy`
82838283
* 如果不存在循环依赖,动态代理在此处完成,否则会提前创建
82848284
8285-
* 循环依赖检查:如果存在循环依赖,在属性填充阶段会生成Bean对象的动态代理,则缓存中放置了提前生成的代理对象,然后使用原始bean继续执行初始化,所以返回最终bean前,把原始bean置换为代理对象返回
8285+
* 循环依赖检查:如果存在循环依赖,在属性填充阶段会生成Bean对象的动态代理,则缓存中放置了提前生成的代理对象,然后使用原始bean继续执行初始化,所以返回最终bean前,把原始bean置换为代理对象返回
82868286
82878287
存在循环依赖,在初始化的后置处理中不会重新创建代理对象,真正创建动态代理Bean的阶段是在获取提前引用阶段,**循环依赖**详解,看后置处理源码:
82888288
@@ -8622,21 +8622,20 @@ AnnotationAwareAspectJAutoProxyCreator是这种类型的后置处理器:Instan
86228622
`if(是否实现接口)`为真进入:`applyBeanPostProcessorsBeforeInstantiation`方法
86238623
86248624
* `this.advisedBeans.containsKey(cacheKey)`:判断当前bean是否在advisedBeans中(保存了所有需要增强bean)
8625-
8626-
* `isInfrastructureClass`:判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者(子类中)是否是切面Aspect
8627-
8625+
* `isInfrastructureClass`:判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者(子类中)是否是切面Aspect
86288626
* 是否需要跳过:子类`AspectJAwareAdvisorAutoProxyCreator.shouldSkip()`
86298627
86308628
* `findCandidateAdvisors()`:获取候选的增强器(切面里面的通知方法)每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor**(AAAPC)**
86318629
86328630
* `if()`:判断每一个增强器是否是 AspectJPointcutAdvisor 类型的,返回true,否则继续执行
8633-
* `return super.shouldSkip(beanClass, beanName)`:永远返回false
8634-
8631+
* `return super.shouldSkip(beanClass, beanName)`:永远返回false
86358632
* `getCustomTargetSource(beanClass, beanName)`:返回为空,doCreateBean()
8633+
86368634
8637-
**进入applyBeanPostProcessorsAfterInitialization:后置处理器创建AOP**
8638-
8639-
```java
8635+
8636+
**进入applyBeanPostProcessorsAfterInitialization:后置处理器创建AOP**
8637+
8638+
```java
86408639
//如果Bean被子类标识为要代理的bean,则使用配置的拦截器创建代理
86418640
public Object postProcessAfterInitialization(@Nullable Object bean,String bN){
86428641
if (bean != null) {
@@ -8650,32 +8649,32 @@ AnnotationAwareAspectJAutoProxyCreator是这种类型的后置处理器:Instan
86508649
return bean;
86518650
}
86528651
```
8653-
8654-
创建动态代理:`wrapIfNecessary()`调用`createProxy()`(wrap包装)
8655-
8656-
注释:Create proxy if we have advice
8657-
8658-
* `getAdvicesAndAdvisorsForBean()`:获取当前bean的所有增强器 (通知方法),**为空就直接返回**
8659-
8660-
* findEligibleAdvisors():找到哪些通知方法是需要切入当前bean方法的
8652+
8653+
创建动态代理:`wrapIfNecessary()`调用`createProxy()`(wrap包装)
8654+
8655+
注释:Create proxy if we have advice
8656+
8657+
* `getAdvicesAndAdvisorsForBean()`:获取当前bean的所有增强器 (通知方法),**为空就直接返回**
8658+
8659+
* findEligibleAdvisors():找到哪些通知方法是需要切入当前bean方法的
86618660
* AopUtils.findAdvisorsThatCanApply():获取到能在bean使用的增强器
86628661
* sortAdvisors(eligibleAdvisors):给增强器排序
8663-
8664-
* `this.advisedBeans.put(cacheKey, Boolean.TRUE)`:保存当前bean在advisedBeans中
8665-
8666-
* `Object proxy = createProxy(...)`:如果增强器不为空就创建代理,创建当前bean的代理对象
8667-
8668-
* buildAdvisors(beanName, specificInterceptors):获取所有增强器(通知方法)
8669-
8670-
* 保存到proxyFactory
8671-
8672-
* `return proxyFactory.getProxy(getProxyClassLoader())`:返回代理对象
8673-
8674-
* ProxyFactory类:`return createAopProxy().getProxy(classLoader)`
8675-
8676-
DefaultAopProxyFactory类:给容器中返回当前组件使用增强了的代理对象
8677-
8678-
```java
8662+
8663+
* `this.advisedBeans.put(cacheKey, Boolean.TRUE)`:保存当前bean在advisedBeans中
8664+
8665+
* `Object proxy = createProxy(...)`:如果增强器不为空就创建代理,创建当前bean的代理对象
8666+
8667+
* buildAdvisors(beanName, specificInterceptors):获取所有增强器(通知方法)
8668+
8669+
* 保存到proxyFactory
8670+
8671+
* `return proxyFactory.getProxy(getProxyClassLoader())`:返回代理对象
8672+
8673+
* ProxyFactory类:`return createAopProxy().getProxy(classLoader)`
8674+
8675+
DefaultAopProxyFactory类:给容器中返回当前组件使用增强了的代理对象
8676+
8677+
```java
86798678
@Override
86808679
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
86818680
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
@@ -8691,7 +8690,7 @@ AnnotationAwareAspectJAutoProxyCreator是这种类型的后置处理器:Instan
86918690
}
86928691
}
86938692
```
8694-
8693+
86958694
4. 给容器中返回使用cglib增强了的代理对象,**初始化完成,加入容器**
86968695
86978696
5. 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程

Java.md

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2779,7 +2779,7 @@ public class Student {
27792779

27802780
#### 概述
27812781

2782-
**String 被声明为 final,因此它不可被继承 (Integer 等包装类也不能被继承)**
2782+
**String 被声明为 final,因此不可被继承 (Integer 等包装类也不能被继承)**
27832783

27842784
```java
27852785
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
@@ -2790,8 +2790,9 @@ public final class String implements java.io.Serializable, Comparable<String>, C
27902790
}
27912791
```
27922792

2793-
在 Java 9 之后,String 类的实现改用 byte 数组存储字符串,同时使用 `coder` 来标识使用了哪种编码。
2794-
value 数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组,并且 String 内部没有改变 value 数组的方法,因此可以**保证 String 不可变**,也保证线程安全
2793+
在 Java 9 之后,String 类的实现改用 byte 数组存储字符串,同时使用 `coder` 来标识使用了哪种编码
2794+
2795+
value 数组被声明为 final,这意味着 value 数组初始化之后就不能再引用其它数组,并且 String 内部没有改变 value 数组的方法,因此可以**保证 String 不可变,也保证线程安全**
27952796

27962797
**注意:不能改变的意思是每次更改字符串都会产生新的对象,并不是对原始对象进行改变**
27972798

@@ -2818,13 +2819,10 @@ s = s + "cd"; //s = abccd 新对象
28182819

28192820
使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 "abc" 字符串对象):
28202821

2821-
- 通过构造方法创建
2822-
2823-
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
2822+
- 通过构造方法创建:通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
28242823

2825-
- 直接赋值方式创建
2824+
- 直接赋值方式创建:以“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会在 String Pool 中创建一个字符串对象,并在字符串池中维护
28262825

2827-
以“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会在 String Pool 中创建一个字符串对象,并在字符串池中维护
28282826

28292827
#### 常用API
28302828

@@ -14595,7 +14593,9 @@ public class MyRunnable implements Runnable{
1459514593
5.把未来任务对象包装成线程对象
1459614594
6.调用线程的start()方法启动线程
1459714595

14598-
`public FutureTask(Callable<V> callable)`:未来任务对象,其实就是一个Runnable对象,这样就被包装成线程对象,未来任务对象可以在线程执行完毕之后去**得到线程的执行结果**
14596+
`public FutureTask(Callable<V> callable)`:未来任务对象,在线程执行完后**得到线程的执行结果**
14597+
14598+
* 其实就是Runnable对象,这样被包装成未来任务对象
1459914599

1460014600
`public V get()`:同步等待 task 执行完毕的结果
1460114601

@@ -18098,6 +18098,93 @@ class MyAtomicInteger {
1809818098

1809918099

1810018100

18101+
***
18102+
18103+
18104+
18105+
### final
18106+
18107+
#### 原理
18108+
18109+
```java
18110+
public class TestFinal {
18111+
final int a = 20;
18112+
}
18113+
```
18114+
18115+
字节码:
18116+
18117+
```java
18118+
0: aload_0
18119+
1: invokespecial #1 // Method java/lang/Object."<init>":()V
18120+
4: aload_0
18121+
5: bipush 20 //将值直接放入栈中
18122+
7: putfield #2 // Field a:I
18123+
<-- 写屏障
18124+
10: return
18125+
```
18126+
18127+
final 变量的赋值通过 putfield 指令来完成,在这条指令之后也会加入写屏障,保证在其它线程读到它的值时不会出现为 0 的情况
18128+
18129+
其他线程访问final修饰的变量会复制一份放入栈中,效率更高
18130+
18131+
18132+
18133+
***
18134+
18135+
18136+
18137+
#### 不可变
18138+
18139+
不可变:如果一个对象不能够修改其内部状态(属性),那么就是不可变对象
18140+
18141+
不可变对象线程安全的,因为不存在并发修改,是另一种避免竞争的方式
18142+
18143+
String 类也是不可变的,该类和类中所有属性都是 final 的
18144+
18145+
* 类用 final 修饰保证了该类中的方法不能被覆盖,防止子类无意间破坏不可变性保
18146+
18147+
* 属性用 final 修饰保证了该属性是只读的,不能修改
18148+
18149+
```java
18150+
public final class String
18151+
implements java.io.Serializable, Comparable<String>, CharSequence {
18152+
/** The value is used for character storage. */
18153+
private final char value[];
18154+
//....
18155+
}
18156+
```
18157+
18158+
更改String类数据时,会构造新字符串对象,生成新的 char[] value,这种通过创建副本对象来避免共享的方式称之为**保护性拷贝(defensive copy)**
18159+
18160+
18161+
18162+
***
18163+
18164+
18165+
18166+
### 无状态
18167+
18168+
无状态:因为成员变量保存的数据也可以称为状态信息,因此没有成员变量
18169+
18170+
Servlet 为了保证其线程安全,一般不为 Servlet 设置成员变量,这种没有任何成员变量的类是线程安全的
18171+
18172+
18173+
18174+
***
18175+
18176+
18177+
18178+
## 线程池
18179+
18180+
18181+
18182+
18183+
18184+
18185+
18186+
18187+
1810118188

1810218189

1810318190

Web.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5167,7 +5167,7 @@ Filter:过滤器,是JavaWeb三大组件之一,另外两个是Servlet和Lis
51675167

51685168

51695169

5170-
### Filter相关类
5170+
### 相关类
51715171

51725172
#### Filter类
51735173

@@ -5584,11 +5584,13 @@ Filter初始化函数init的参数是FilterConfig 对象
55845584

55855585

55865586

5587-
### 五种拦截行为
5587+
### 拦截行为
55885588

55895589
Filter过滤器默认拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,需要配置web.xml
55905590

5591-
开启功能后,当访问页面发生相关行为后,会执行过滤器的操作。
5591+
开启功能后,当访问页面发生相关行为后,会执行过滤器的操作
5592+
5593+
五种拦截行为:
55925594

55935595
```xml
55945596
<!--配置过滤器-->
@@ -5669,7 +5671,7 @@ Filter过滤器默认拦截的是请求,但是在实际开发中,我们还
56695671

56705672

56715673

5672-
### 过滤器与Servlet
5674+
### 对比Servlet
56735675

56745676
| 方法/类型 | Servlet | Filter | 备注 |
56755677
| -------------------------------------------------- | --------------------------------- | --------------------------------------------- | ------------------------------------------------------------ |

0 commit comments

Comments
 (0)