1、Spring
基于servlet 自己设计spring主要流程
1.0 Spring 核心组件
BeanFactory:产生一个新的实例,可以实现单例模式
BeanWrapper:提供统一的get及set方法
ApplicationContext:提供框架的实现,包括BeanFactory的所有功能
Spring 框架中的核心组件只有三个:Core、Context 和 Beans。它们构建起了整个 Spring 的骨骼架构。
1.0.1 初始化
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
1.0.2 ApplicationContext 与 BeanFactory关系
1.1 Spring概述
Context是入口
定位 用的 Reader 结尾的
加载 BeanDefinition保存类信息,包括OOP关系
注册 Factroy、Context 就是把用户所定义的Bean放到IOC容器中(Map)
2、IOC实现原理
围绕Bean来展开
BeanFactory来创建的
reader load
do开头的都是具体干活
ClassPathXmlApplicationContext 通过main方法启动
DispatchServlet
FileSystem
Plugin
Lisenter
parseBeanDefinitions 方法实际是解析xml,把xml中的内容变成BeanDefinition (类信息)
参考图示:
2.1 XML对Bean初始化
2.1.1 默认无参构造函数
-
SimpleInstantiationStrategy 使用默认无参构造方法创建Bean对象
//使用初始化策略实例化 Bean 对象 @Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. //如果 Bean 定义中没有方法覆盖,则就不需要 CGLIB 父类类的方法 if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { //获取对象的构造方法或工厂方法 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; //如果没有构造方法且没有工厂方法 if (constructorToUse == null) { //使用 JDK 的反射机制,判断要实例化的 Bean 是否是接口 final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { //这里是一个匿名内置类,使用反射机制获取 Bean 的构造方法 constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) () -> clazz.getDeclaredConstructor()); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } //使用 BeanUtils 实例化,通过反射机制调用”构造方法.newInstance(arg)”来进行实例化 return BeanUtils.instantiateClass(constructorToUse); } else { // Must generate CGLIB subclass. //使用 CGLIB 来实例化对象 return instantiateWithMethodInjection(bd, beanName, owner); } }
通过上面的代码分析,我们看到了如果 Bean没有方法被覆盖了,则使用 JDK
的反射机制进行实例化,否 则,使用 CGLIB
进行实例化。
instantiateWithMethodInjection
方 法 调 用 SimpleInstantiationStrategy
的 子 类 CglibSubclassingInstantiationStrategy
使用 CGLIB
来进行初始化,其源码如下:
//使用 CGLIB 进行 Bean 对象实例化
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
//创建代理子类
Class<?> subclass = createEnhancedSubclass(this.beanDefinition); Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass); }
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
Factory factory = (Factory) instance; factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) { //CGLIB 中的类
Enhancer enhancer = new Enhancer();
//将 Bean 本身作为其基类 enhancer.setSuperclass(beanDefinition.getBeanClass()); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader(); enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
}
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition)); enhancer.setCallbackTypes(CALLBACK_TYPES);
//使用 CGLIB 的 createClass 方法生成实例对象
return enhancer.createClass();
}
}
CGLIB 是一个常用的字节码生成器的类库
,它提供了一系列 API 实现 java字节码的生成和转换功能
。 我们在学习 JDK 的动态代理时都知道,JDK 的动态代理只能针对接口
,如果一个类没有实现任何接口, 要对其进行动态代理只能使用 CGLIB。
2.1.2 AnnotationConfigApplicationContext
对注解 Bean 初始化
Spring 中 , 管 理 注 解 Bean 定 义 的 容 器 有 两 个 : AnnotationConfigApplicationContext
和 AnnotationConfigWebApplicationContext
。这两个类是专门处理 Spring 注解方式配置的容器,直 接依赖于注解作为容器配置信息来源的 IOC 容器。 AnnotationConfigWebApplicationContext是
AnnotationConfigApplicationContext的web版本,两者的用法以及对注解的处理方式几乎没有什 么差别。
现在来看看 AnnotationConfigApplicationContext
的源码:
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
//保存一个读取注解的 Bean 定义读取器,并将其设置到容器中
private final AnnotatedBeanDefinitionReader reader;
//保存一个扫描指定类路径中注解 Bean 定义的扫描器,并将其设置到容器中
private final ClassPathBeanDefinitionScanner scanner;
//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其 register() //方法注册配置类,并调用 refresh()方法刷新容器,触发容器对注解 Bean 的载入、解析和注册过程
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的 Bean 自动注册到容器中
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的 Spring Bean,将其注册到容器中
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(environment);
this.scanner.setEnvironment(environment);
}
//为容器的注解 Bean 读取器和注解 Bean 扫描器设置 Bean 名称产生器
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.reader.setBeanNameGenerator(beanNameGenerator);
this.scanner.setBeanNameGenerator(beanNameGenerator);
getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
}
//为容器的注解 Bean 读取器和注解 Bean 扫描器设置作用范围元信息解析器
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.reader.setScopeMetadataResolver(scopeMetadataResolver);
this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
//为容器注册一个要被处理的注解 Bean,新注册的 Bean,必须手动调用容器的 //refresh()方法刷新容器,触发容器对新注册的 Bean 的处理
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.reader.register(annotatedClasses);
}
//扫描指定包路径及其子包下的注解类,为了使新添加的类被处理,必须手动调用 //refresh()方法刷新容器
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
...
}
通过对 AnnotationConfigApplicationContext 的源码分析,我们了解到 Spring 对注解的处理分为 两种方式: (1).直接将注解 Bean 注册到容器中:
可以在初始化容器时注册;也可以在容器创建之后手动调用注册方法向容器注册,然后通过手动刷新容 器,使得容器对注册的注解 Bean 进行处理。
(2).通过扫描指定的包及其子包下的所有类:
在初始化注解容器时指定要自动扫描的路径,如果容器创建以后向给定路径动态添加了注解 Bean,则 需要手动调用容器扫描的方法,然后手动刷新容器,使得容器对所注册的 Bean 进行处理。
3、SpringAOP
面向切面编程 -> 代理(JDKProxy、CgLib) 解耦
…
4、编程思想与总结
Spring 思想 | 应用场景(特点) | 一句话归纳 |
---|---|---|
AOP | Aspect Oriented Programming(面向切面编程) 找出多个类中有一定规律的代码,开发时拆开,运行时再合并。 面向切面编程,即面向规则编程。 | 解耦,专人做专事。 |
OOP | Object Oriented Programming(面向对象编程) 归纳总结生活中一切事物。 | 封装、继承、多态 |
BOP | Bean Oriented Programming(面向Bean编程) 面向Bean(图通的Java类)程序设计 | 一切从Bean开始 |
IOC | Inversion Of Control(控制反转) | 转交控制权 |
DI/DL | Dependency Injection(依赖注入)或者Dependancy Lookup(依赖查找) 依赖注入、依赖查找,Spring不仅保存自己创建的对象,而且保存对象与对象之间的关系。注入即赋值,主要三种发共识构造方法、set方法、直接赋值 | 先理清关系再赋值 |
参考: GP-Tom老师学习源码