spring相关
核心组件
由此可以看到各组件的相互依赖关系。
test可以单侧
CoreContainer
- beans beanFactory
- core 核心工具类
- context applicationContext 容器实例化
- SpEL 表达式语言 操作对象
AOP 代理 通知
Aspects 集成子AspectJ,提供多种AOP实现方法。
Instrumentation
Messaging
JDBC 简化JDBC使用 一些列模板
- Transactions 事务
WEB
- web支持 通过service或listener
- WebMVC
- WebSorcket 通信协议,
- WebFlux 异步非阻塞
源码核心模块
- spring-core 核心工具类最基础服务;
- spring-beans 对象管理,依赖管理 bean的定义解析及创建。BeanFactory接口最重要
- Spring-context:扩展了beanFactory,
- spring-aop:支持部分AOP功能。
- JDK动态代理
- Cglib代理
- 运行时织入,仅支持方法及编织,仅支持方法执行切入点
声命周期
作用域
事务传播机制
事务隔离级别
spring用到哪些设计模式
常用注解
@response body
@Transactional 事务机制
spring注入
IOC AOP 原理
日志是什么阶段输出的
怎么解决循环依赖
springCloud
hystrix 信号量怎么用,常用的限流方式有哪些
feign
ribbon
反射
运行时判断任意一个对象所属的类;运行时获取类的对象;运行时访问java对象的属性构造方法;
java.lang.reflect类库里的主要的类
- Field:成员变量
- Method:类中的方法
- Constructor:构造方法
- Array:动态创建数组和访问数组的静态方法
用来表示运行时类型信息的对应类
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement { 只能够通过JVM能够创建Class类的实例,因为构造方法被私有化了。 private Class(ClassLoader loader) { classLoader = loader; }
}
JVM启动的时候通过.class文件,加载到内存中,并创建出相应的对象来。
反射的常用三种方式
- Object ---> getClass();
- 任何数据类型都有一个静态的class属性
- 通过class类的静态方法forName(String className)(常用)
在运行期间,一个类,只有一个与之对应的Class对象产生。
主要用法
- 获取类的构造方法
- 获取类的成员变量
- 获取类的成员方法
Class clazz = Class.forName("demo.xxx.xxx");
这个对象有很多方法,可以获取不同级别的字段。
需要记录类名和package
用XML来保存类相关信息以提供反射调用。
<bean id="welcomeService" class="com.imooc.service.impl.WelcomeServiceImpl"/>
用注解来保存相关信息以供反射调用。
@Service ;@Resource;等
注解
@Annotation
所有的注解类,都继承自java.lang.annotation.Annotation这个接口。
但是我们自己创建注解类的时候,并没有发现注解类和Annotation有什么直接联系。
可以通过反编译查看。javac后javap -verbose 包.类名。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface TestAnnotation { }
看到继承自Annotation。
注解功能
- 特定的标记,用于告诉编译器信息;
- 编译时动态处理,如动态生成代码
- 运行时动态处理,作为额外信息的载体,如获取注解信息。
注解分类
- 标准注解
- 元注解 标记Annotation的Annotation
- @Target 注解的作用目标
- 修饰注解能作用在什么场景,可以多选:有枚举
- packages、types
- 类型成员
- 方法参数和本地变量
- @Retention 注解的生命周期 注解在什么范围内有效 有枚举 RUNTIME: bean实例 通过反射注入过来
- @Documented 是否应当被包含在JavaDoc文档中 默认是不包括的
- @Inherited 是否允许子类集成该注解
- @Target 注解的作用目标
- 自定义注解
自定义注解
- 创建一个人物信息的注解 public @interface XXX
- @Target(ElementType.FIELD)作用在类成员变量上
- @Retention(RUNTIME) 运行时
代码一:
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface PersonInfoAnnotation { // 名字 public String name(); // 年龄 public int age() default 19; // 性别 public String gender() default "男"; // 开发语言 public String[] language(); }
@Target({ElementType.TYPE, ElementType.METHOD}) 作用在类和方法上 @Retention(RetentionPolicy.RUNTIME) public @interface CourseInfoAnnotation { //课程名称 public String courseName(); //课程标签 public String courseTag(); //课程简介 public String courseProfile(); //课程序号 public int courseIndex() default 303; }
@CourseInfoAnnotation(courseName = "XXX", courseTag = "XXX",courseProfile = "XXXXXX") public class ImoocCourse { @PersonInfoAnnotation(name = "XX", language = {"Java","C++"}) private String author; @CourseInfoAnnotation(courseName = "XXX",courseTag = "XXX",courseProfile = "XXXXX",courseIndex = 144) public void getCourseInfo() { } }
加完注解之后,并没有实际的作用,因为没有对注解进行改动。
可以看到
Class类实现了一个AnnotatedElement的接口。
反射Constructor继承Executable
Executable继承了AccessibleObject
AccessibleObject也实现了AnnotatedElement
Field类继承了AccessibleObject
AccessibleObject也实现了AnnotatedElement
Method类继承了Executable
Executable继承了AccessibleObject
AccessibleObject也实现了AnnotatedElement
与反射相关的类都实现了AnnotatedElement接口
AnnotatedElement常用方法
- getAnnotations() 获取所有注解
- getAnnotation() 获取一个注解
- isAnnotationPresent()用于判断指定类型的注解是否存在 是TRUE;
对自定义注解的改动
在我们上面ImoocCourse这个类,里面有多个注解。
我们可以通过反射以及相关方法,获取ImoocCourse里的成员及属性。
这么做的前提是注解是RUNTIME类型的。
注解的底层实现
获取注解标签属性的值
JVM会为注解生成代理对象
在IDEA启动的VM options里输入:-D jdk.proxy.ProxyGenerator.saveGeneratorFiles=ture
可以记录下中间层的文件。
有8个动态代理对象。
其中和属性相关的language有一个方法与其对应,返回类型也一样,方法体是用得invoke方法
构造函数:InvocationHandler有invoke方法,
注解会通过:AnnotationInvocationHandler,调用这个invoke()方法
在IDEA启动的VM options里输入:-D jdk.proxy.ProxyGenerator.saveGeneratorFiles=ture -XX:+TraceClassLoading
多了很多类的名字,有这个AnnotationInvocationHandler,也可以加断点来确认。
AnnotationInvocationHandler里
会依据属性名返回对应值,判断是否是数组,数组返回克隆版本,非数组直接返回。
总结:
- 通过键值对的形式为注解属性赋值。
- 编译器检查注解的使用范围,将注解信息写入元素属性表。
- 运行时JVM将RUNTIME的所有注解属性取出并最终存入map里。
- 创建AnnotationInvocationHandler实例并传入前面的map
- JVM使用JDK动态代理为注解生成代理类,并初始化处理器。
- 通过调用AnnotationInvocationHandler的Invoke方法,通过传入方法名返回注解对应的属性值。
IOC 控制反转
主要用得原理是DI 依赖注入
依赖注入的方法Setter、Interface、Constructor、Annotation
IOC的优势
避免在各处new来创建类,并且可以做到统一
创建实例的时候不需要了解其中的细节。
反射+工厂模式的合体,满足开闭原则。
------------读spring源码---------------