[关闭]
@x-power 2019-10-16T14:52:31.000000Z 字数 7001 阅读 627

Spring

Spring


Spring通过配置文件去描述BeanBean之间的依赖关系, 利用Java反射功能实例化Bean并建立Bean之间的依赖关系. Spring IoC在完成这些底层工作的基础之上还提供了Bean实例缓存, 生命周期管理, Bean代理实例, 事件发布, 资源装载等高级服务.


生命周期管理

Bean工厂(com.springframework.beans.factory.BeanFactory): 是Spring框架中最核心的接口, 它提供了高级IoC的配置机制. BeanFactory使管理不同类型的Java对象成为可能.

应用上下文(com.springframework.context.ApplicationContext):建立在BeanFactory基础之上提供了更多面向引用的功能, 它提供了国际化支持和框架事件体系, 更加易于创建实际应用.


我们一般称BeanFactoryIoC容器, 而称ApplicationContext为应用上下文或者Spring容器.
BeanFactory是Spring框架的基础设置, 面向Spring本身; ApplicationContext面向使用Spring框架的开发者, 几乎所有的应用场合都可以直接使用ApplicationContext .

Spring框架是工厂, 而被创建的类对象本身也可能是一个工厂, 这就形成了创建工厂的工厂.


BeanFactory

BeanFactory是类的通用工厂. 他可以创建并管理各种类的对象, 这些类就是POJO, Spring称这些被创建并管理的对象为Bean.

1. 初始化

我们在Spring配置文件中创建Bean People, 然后通过BeanFactory加载配置文件, 启动IoC容器.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="people" class="net.deniro.springBoot.spring4.IoC.People"
  7. p:name="deniro"
  8. p:age="25"
  9. />
  10. </beans>
  1. ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  2. Resource resource = resolver.getResource("classpath:beans.xml");
  3. System.out.println("getURL:" + resource.getURL());
  4. DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
  5. XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
  6. reader.loadBeanDefinitions(resource);
  7. System.out.println("Bean 工厂已完成初始化");
  8. People people = factory.getBean("people", People.class);
  9. System.out.println("People 已被创建");
  10. System.out.println(people.toString());

ApplicationContext

ApplicationContext由BeanFactory派生而来, 提供了很多的实际应用的功能. 在BeanFactory中, 很多功能需要编程实现, 而在ApplicationContext中则可以通过配置的方式去实现解耦.

  1. //从类路径加载配置文件
  2. // 提供一组配置文件, Spring IoC在资源装配的时候, 会将其进行整合.
  3. ApplicationContext context3 = new ClassPathXmlApplicationContext(new
  4. String[]{"beans.xml", "beans2.xml"});
  5. //从文件系统加载配置文件
  6. ApplicationContext context2 = new FileSystemXmlApplicationContext("d:/beans.xml");

Spring支持注解配置, 主要功能来自于Spring的一个名为JavaConfig的子项目, 目前JavaConfig已经升级为Spring核心框架的一部分, 一个标注@Configuration注解的POJO既可以为Spring提供所需的Bean配置信息.

  1. @Configuration//表示这个类包含配置信息
  2. public class Beans {
  3. //定义 Bean
  4. @Bean(name = "people")
  5. public People build() {
  6. People people = new People();
  7. people.setAge(25);
  8. people.setName("deniro");
  9. return people;
  10. }
  11. }
  1. ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);
  2. People people = context.getBean("people", People.class);
  3. Assert.assertNotNull(people);

Bean的生命周期


Spring IoC 如何实现


Bean工厂(com.springframework.beans.factory.BeanFactory): 是Spring框架中最核心的接口, 它提供了高级IoC的配置机制. BeanFactory使管理不同类型的Java对象成为可能.

应用上下文(com.springframework.context.ApplicationContext):建立在BeanFactory基础之上提供了更多面向引用的功能, 它提供了国际化支持和框架事件体系, 更加易于创建实际应用.


我们一般称BeanFactoryIoC容器, 而称ApplicationContext为应用上下文或者Spring容器.
BeanFactory是Spring框架的基础设置, 面向Spring本身; ApplicationContext面向使用Spring框架的开发者, 几乎所有的应用场合都可以直接使用ApplicationContext .

Spring框架是工厂, 而被创建的类对象本身也可能是一个工厂, 这就形成了创建工厂的工厂.


Spring AOP

有了IOC其中CGLIB解决了静态代理和动态代理对类的接口的依赖性和功能依赖性的问题之后, 使得将所有类(非final修饰的类)都实现代理模式成为可能(CHLIB是基于继承的方式做的动态代理). 所以IOC是AOP的基础.

面向切面编程, 在我们的应用中, 经常需要做一些事情, 但是这些事情与核心业务无关, 比如要记录所有update的执行时间, 操作人信息等等 到日志. 通过 AOP就可以在不修改原有代码的情况下完成需求.

AOP思想: 基于动态代理把各个事务单独抽取出来, 然后通过配置去寻找他的前置,后置,异常等方法.

实际上就是通过 动态代理设计模式的动态代理方法, 使用 InvocationHandler传入类加载器和实现的接口 以 获取代理运行的被代理类的函数的方法名和传入的参数, 然后通过反射创建被代理类完成其功能, 并在其前和其后加入其它功能.

JDK动态代理类和委托类需要实现同一个接口, 也就是说只有实现了某个接口的类可以使用Java动态代理机制. 但是, 事实上使用中并不是遇到的所有类都会有实现接口. 因此, 对于没有实现接口的类, 就不能使用该机制. CGLIB则可以实现对类的动态代理.


Spring事务实现方式

编程式事务指的是通过编码方式实现事务, 即类似于JDBC编程实现事务管理.

声明式事务管理又有两种实现方式:
- 基于xml配置文件的方式
- 另一个是在业务方法上进行@Transaction注解, 将事务规则应用到业务逻辑中.


划分处理单元IOC

通过IOC将事务的各种配置放到IOC容器之中.

由于Spring解决的问题是对单个数据库进行局部事务处理的, 具体的实现首先用Spring中的IOC划分了事务处理单元. 并且将对事务的各种配置放到了IOC容器中(设置事务管理器, 设置事务的传播特性以及隔离机制).

AOP拦截需要进行事务处理的类

Spring事务处理模块是通过AOP功能来实现声明式事务处理的, 具体操作(比如事务实行的配置和读取, 事务对象的抽象), 用TransactionProxyFactoryBean接口来使用AOP功能, 生成proxy代理对象. 通过TransactionProxyFactoryBean完成对代理方法的拦截, 将事务的处理功能编织到拦截的方法中. 读取IOC容器事务配置属性, 转化为Spring事务处理需要的内部数据结构,转化为TransactionAttribute表示的数据对象.


SpringMVC 运行流程

此处输入图片的描述


SpringMVC的启动流程

  1. <!-- 分发所有的HTTP 请求和响应. -->
  2. <servlet>
  3. <servlet-name>springServlet</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <init-param>
  6. <param-name>contextConfigLocation</param-name>
  7. <param-value>classpath*:/spring-mvc*.xml</param-value>
  8. </init-param>
  9. <load-on-startup>1</load-on-startup>
  10. </servlet>
  11. <servlet-mapping>
  12. <servlet-name>springServlet</servlet-name>
  13. <url-pattern>/</url-pattern>
  14. </servlet-mapping>

SpringMVC启动过程大致分为两个阶段:


Spring单例实现原理.

我们实现的单例,不论是懒汉,饿汉或者是双重加锁且进制代码重排, 都需要在定义类的时候对其单例模式进行定义, 但是在Spring中却并没有这样做.


单例模式 / 原型模式

单例模式: 确保每个类只有一个实例, 而且自行实例化并向整个系统提供这个实例.

当多用户同时请求一个服务的时候, 容器会给每一个请求分配一个线程, 这时多个线程会并发执行该请求对应的业务逻辑(成员方法). 重要的是, 如果这时候逻辑处理中有对该单例属性的修改(有状态Bean), 则必须考虑线程同步问题.


同步机制的比较

ThreadLocal和线程同步机制相比有什么优势呢?
- ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题.
- 同步机制: 通过对象的锁机制保证同一时间只有一个线程访问变量, 这时候变量是多个线程共享的, 使用同步机制要求程序员缜密的分析什么时候对变量进行读写, 什么时候需要锁定某个对象, 什么时候释放对象锁等复杂的问题, 程序设计和编写的难度比较大.
- ThreadLocal: 从另一个角度去避免上述的困难并且解决并发访问, ThreadLocal会为每一个线程提供一个独立的变量副本, 从而隔离了多个线程对数据的访问冲突. 因为每一个线程都有自己的变量副本, 从而也就没必要对改变量进行同步了. ThreadLocal提供了线程安全的共享对象, 在编写多线程代码的时候, 可以把不安全的对象封装进ThreadLocal.
- 在算法常用的角度来说就是 同步机制 以牺牲时间复杂度的代价降低空间复杂度. ThreadLocal以牺牲空间复杂度的代价降低时间复杂度.

Spring使用ThreadLocal解决线程安全问题. 按上述只有无状态的Bean才可以在多线程情况下共享. 但是在Spring中绝大部分的Bean都可以声明为Singleton, 这是因为Spring对一些 有状态的Bean使用了ThreadLocal进行处理.

原型模式的使用情况: 自己生命的有状态的Bean在高并发的情况下, 可以将其声明为Prototype.

这样在基本情况下我们使用 单例模式就可以了 , 对于我们声明的一些 有状态Bean, 对其@Scope(ConfigurableFactory.SCOPE_PROTOTYPE)装饰.


添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注