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 是否允许子类集成该注解 
  • 自定义注解

自定义注解

  1. 创建一个人物信息的注解 public @interface XXX
  2. @Target(ElementType.FIELD)作用在类成员变量上
  3. @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源码---------------

 

posted @ 2023-05-27 20:38  CodingOneTheWay  阅读(4)  评论(0编辑  收藏  举报
回到顶部