Spring

第一轮总结性笔记

说起Spring,我们就挑重点能理解的来说,因为源码我暂时着实看不懂

说到Spring,就必须提到 IOC DI AOP这三个关键词,当然也是面试常问,一般让你介绍Spring,都是从这里开始

今天我就对其进行浅层面(涉及一点源码)的对其复习一波:

首先说 控制反转: IOC

以前我们使用对象,都是通过手动 new的方式创建对象,当我们使用了Spring后,我们将对象的创建权利反转给Spring,由Spring容器 统一管理对象的创建和依赖关系以及生命周期等,说到IOC就必须说到IOC容器,其本质就是创建类的实列的工厂 ,并且对类的实列进行管理 ,下面有重点介绍

其次就是依赖注入 : DI

1.动态的给一个对象向其提供它所需要依赖的其他对象或属性有树洞和自动之分,现在一般都是注解开发,

2.手动装配就是在<bean>标签中通过<property>注入,这种需要该属性提供set方法

3.自动装配通过@Autowrite 和 @Resource注解,进行装配

@Autowrite : 根据类型查找实列(单列) ,并赋值完成注入;

@Resource : 根据Bean的名称查找获取实列,完成装配;

最后就是面向切面: AOP

aop可以说是Spring中的和超级重点了,使用技术:反射、代理,代理包括jdk代理和cglib反向代理;

简单理解就是针对目标对象进行动态代理,横向增强JavaBean

AOP术语:

  1. target:目标类,需要被代理的类。userService;

  2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法;

  3. PointCut 切入点:已经被增强的连接点。例如:addUser();

  4. advice 通知/增强,增强代码。例如:after、before

  5. Weaving(织入) : 是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程;

  6. proxy : 代理类

  7. Aspect(切面) : 是切入点pointcut和通知advice的结合

给我五块钱,我给你粗略的说说Spring容器 ( IOC容器 ) 初始化过程 ?

在理笔记之前,我们先弄清楚几个概念:web服务器 、web容器、spring容器;

1.web服务器 : 也就是servlet容器,比如我们常用的 Tomcat 还有Jetty Jboss等;

2.web容器 : 即Servlet上下文(Application) ServletContext,Servlet三大作用域中生命周期最长的那个

3.Spring容器: 也叫 IOC容器,Spring学习的重点,即Spring上下文 SpringContext

所谓的IOC容器:指的是Bean工厂里面的一个Map储存结构(K: bean标签中的id属性值 --V: 对象的实列对象)

Spring中的工厂早起就BeanFactory,Spring容器顶层接口,采用的事延迟加载机制,现在用的是ApplicationContext,对注册为单列的Bean在读取配置文件是就是加载配置妥当,ApplicationContext是继承BeanFactory的一个接口,两个接口最下层做事情的都是DefaultListableBeanFactory

初始化过程:

1.web服务器启动的时候会读取web.xml,启动我们配置的ContextLoaderListener监听器

2.服务器启动后创建servlet上下文的时候会触发ContextLoaderLister监听器的contextInitialized()方法;

3.contextInitialized()方法中调用initWebApplicationContext()方法创建Spring容器和生产Bean对象(反射);

4.initWebApplicationContext通过createWebApplicationContext()方法会创建WebApplicationContext;

5.WebApplicationContext是一个接口,这里创建的是它的默认实现类:XmlWebApplicationContext(真正的容器)

6.通过configureAndRefreshWebApplicationContext()方法加载Spring的配置文件,创建Bean

7.通过servletContext.setAttribute()方法,将spring容器context挂载到ServletContext 这个web容器上下文中

大致如下:

说明:(跟着源码可以参考参考,我暂时也没弄明白,先读读有个印象)

1.ResourceLoader加载Spring配置信息,并使用Resource表示这个配置文件的资源

2.BeanDefinitionReader读取Resource所指向的配置文件资源,解析文件中每一个<bean>标签,生成对应的BeanDefinition对象,并保 存到BeanDefinitionRegistry中

3.容器扫描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射机制自动识别出Bean工厂后处理后器(实现BeanFactoryPostProcessor接口)的Bean,然后调用这些Bean工厂后处理器对4.BeanDefinitionRegistry中的BeanDefinition进行加工处理。主要完成以下两项工作

  1)对使用到占位符的<bean>元素标签进行解析,得到最终的配置值,这意味对一些半成品式的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象;

  2)对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean(实现java.beans.PropertyEditor接口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry);

5.Spring容器从BeanDefinitionRegistry中取出加工后的BeanDefinition,并调用InstantiationStrategy着手进行Bean实例化的工作;

6.在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper提供了很多以Java反射机制操作Bean的方法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置工作;

7.利用容器中注册的Bean后处理器(实现BeanPostProcessor接口的Bean)对已经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean。

8.Spring容器确实堪称一部设计精密的机器,其内部拥有众多的组件和装置。Spring的高明之处在于,它使用众多接口描绘出了所有装置的蓝图,构建好Spring的骨架,继而通过继承体系层层推演,不断丰富,最终让Spring成为有血有肉的完整的框架。所以查看Spring框架的源码时,有两条清晰可见的脉络:

  1)接口层描述了容器的重要组件及组件间的协作关系;

  2)继承体系逐步实现组件的各项功能。

接口层清晰地勾勒出Spring框架的高层功能,框架脉络呼之欲出。有了接口层抽象的描述后,不但Spring自己可以提供具体的实现,任何第三方组织也可以提供不同实现, 可以说Spring完善的接口层使框架的扩展性得到了很好的保证。纵向继承体系的逐步扩展,分步骤地实现框架的功能,这种实现方案保证了框架功能不会堆积在某些类的身上,造成过重的代码逻辑负载,框架的复杂度被完美地分解开了。

Spring组件按其所承担的角色可以划分为两类:

1)物料组件:Resource、BeanDefinition、PropertyEditor以及最终的Bean等,它们是加工流程中被加工、被消费的组件,就像流水线上被加工的物料;

2)加工设备组件:ResourceLoader、BeanDefinitionReader、BeanFactoryPostProcessor、InstantiationStrategy以及BeanWrapper等组件像是流水线上不同环节的加工设备,对物料组件进行加工处理。

SpringIOC基于Xml 的认识

在配置文件通过<bean>标签配置,该标签最后会加工成一个BeanDefition对象 ( 上面说到的用来描述对象信息的对象)

列子太普通,就是通过ClassPathXmlApplicationContext读取配置文件,获取一个容器ApplicationContext引用

在容器中可以通过两种方式获取对象 传入.class根据类型获取 传入<bean>标签的id获取亦可

在这个过程中,实列化bean的几种方式:

( 默认 ) 使用无参构造函数实列化,如果没有无参构造,创建失败

其次就是静态工厂和实列工厂

SpringDI基于Xml 的认识

构造函数注入: 该实列中有个有参构造方法 分别对 id username 进行赋值 和下面这个配置文件一一对应生效

<bean id="userService" class="com.test.di.service.userServiceImpl">

  <constructor-arg name="id" value="1" />

  <constructor-arg name="username" value="张三" />

<bean>

set方法注入: 手动装配 / 自动装配

手动装配: 通过 <property name="" value=""> 需要在需要的类中给出 set方法才行

自动装配:@AutoWired 和 @Resource

还有一个P名称看见注入数据,本质上还是set方法,不怎么用,不做笔记

依赖注入不同类型的属性:

简单类型 : value | 引用类型 : ref | 集合比较多,需要时即时了解亦可

常用注解讲解

@Component : 相当于一个<bean>标签

  value:指定bean的id,如果不声明,默认类名首字母小写

@Controller (表现层) 、@Service (业务层) 、@Repository (持久层)

  这三个注解是@Component注解的衍生注解

@AutoWired : 默认按照类型装配

@Qualifier : 在@AutoWired注解基础上,再按照Bean的id注入 ( 必须搭配使用)

@Resource : 通过名字进行装配,不属于Spring,是J2EE的注解

  如果没有匹配上,其次选择按照类型装配

@Value :给基本类型和String类型注入值,也可以使用占位符的方式获取配置文件中的值 比如:

  @Value("username") // username 是properties文件中的key

@Scope : 改变作用域分范围,知道 singletonprototype即可

基于Xml 和 注解开发的简单对比

第二轮总结性笔记

Spring的纯注解开发配置

SSM的使用XMl的整合,素有配置地狱的称号,可以纯注解开发将取代配置文件的编写,采用注解的方式配置

@Configuration :用于申明当前类为一个配置类,

@Bean 标注在方法上,该方法返回什么对象,就把该对象装配到Spring容器,一般用于配置非自定义的bean

  该注解默认为单列作用域,可通过@Scope注解重新指定作用域

@ComponentScan : 相当于配置文件中的 context:component-scan 标签,扫描包下注解的作用

@PropertySource : 加载propeties配置文件,编写在类上 相当于context:property-placeholder标签

  列如: @PropertySource(“classpath:jdbc.properties”)

@Impport : 用来组合多个配置类,value:指定其他配置类的字节码文件

  列如 @Import({ JdbcConfig.class})

IOC和DI总结

IOCy原理部分理解:

什么是IOC

声明式Spring容器(IOC容器)

如何创建Spring容器

Spring容器如何初始化

DI原理部分理解:

​什么是依赖

什么事DI(依赖注入)

什么时候进行依赖注入

DI 的方式有哪些

不同数据类型如歌进行注入

Spring整合Junit单元测试

1. 依赖: spring-test 包

2. 通过RunWith( SpringJunit4ClassRunner ) ,指定Spring提供的单元测试的运行器 : SpringJunit4ClassRunner

3. 通过@ContextConfiguration注解,指定Spring运行器需要的配置文件路径

  如:@ContextConfiguration ( locations="classpath:applicationContext.xml") 读取配置文件

  @ContextConfiguration ( classes=SpringConfiguration.class) 读取配置类,纯注解开发模式

4. 通过@AutoWired注解 注入我们需要的数据

SpringAOP原理分析:

aop 是一种思想,通过预编译和运行期动态代理的方式实现程序功能的统一维护的一种实现

利用aop可以对业务逻辑的各个部分进行分割,提高切面的可重用性,我们打比方一个面包片就像我们的一个业务逻辑,我们可以在这个面包片的上面或者下面给它涂上各种酱。在代码中表现为:性能检测、权限验证、日志纪录、事务控制、

Spring AOP 是通过动态代理技术实现,动态代理基于反射设计,动态代理技术的实现有两种

一种是基于接口的JDK动态代理

一种是基于继承的CGLIB动态代理,详细请见:https://www.cnblogs.com/msi-chen/p/10801816.html

SpringAOP的使用 基于 xml / 注解

spring整合包:spring-sapects包 | aop联盟:aopalliance包

确定目前类和通知类,将其交由Spring容器统一管理

配置AOP切面,整体如下:

其中涉及到一个 切入点表达式的知识 :移步这里 https://www.cnblogs.com/msi-chen/p/10206030.html

  execution([修饰符] 返回值类型 包名.类名.方法名(参数))

通过上面的配置我们可以看见 <aop:aspect ref="MyAdvice"> 我们将一个类定义为 通知/增强类

其下有:照着轮子造就OK

  

以上就是基于Xml的方法,下面说说基于注解的方式:

最后再补充一点,使用纯注解的方式:

选择一个类作为配置类,在上面开启相应的注解:

  

在测试的时候,只需要把读取配置文件的方式改成读取配置类的方式即可:

@ContextConfiguration(classes = MyConfiguration.class)  //使用纯注解的方式

关于Spring的Dao开发之JdbcDaoSupport下的jdbcTemplate

由于用的很少很少,一般常用持久层框架为MyBatis或者SpringDataJPA,所以这里简单说一下:

IOC4个包(beans core context expression)、AOP2个包(aspects aopalliance)、

C3P0一个包、MySQL驱动包、SpringJDBC2个包(tx jdbc)、Junit测试包

Dao层实现类继承 JdbcDaoSupport 并注入DataSource通过 this.getJdbcTemplate()即可

事务支持

事务回顾几个特性?各有什么特点?

隔离性的级别有哪些?导致在事务并发时出现几个问题?各自有什么特点?

回忆:原子性 、一致性、隔离性、持久性、

对于原子性的理解就是,我们把一个事务包含的逻辑,看成一个不可分割的单位,要么一起成功,要么一起失败

一致性:那转账来说,无论A怎么向B转账,他们两个账户的总金额是不会变得

隔离性:当多个请求并发访问数据库时,为每一个请求开启的事务不能被其他事务所干扰,要隔离开来

持久性:就是事务一旦提交,数据就会持久化到数据库,是永久、持久性的

回忆:https://www.cnblogs.com/msi-chen/p/10195844.html(搬砖的事情就不干了)

Spring的声明式事务管理

Spring框架事务管理分为编程式事务和声明式事务,前者不推荐使用,不做笔记

  声明式事务又分为Xml方式 和 注解方式,我们都需要掌握使用

首先我们说说Xml方式事务的使用:

  

  第一步说明:配置平台事务管理器,无论是Xml方式还是注解方式都需要的配置

  第二步说明:配置通知,通过其中的属性,我看可以看出我们将平台事务管理器和transfer()联系到了一起,并设置相应的事务传播行为

  第三步说明:切面配置,确定通知应用到那些切入点上

再说说基于注解的,这种运用相对简单,使用广泛:

  

  可以看出,我们只需要配置一个 平台事务管理器,然后通过一个注解开启注解事务,

  在我们需要开启的类 或者方法上加上@Transactional即可

整体结构如下:

  

原文地址:https://www.cnblogs.com/msi-chen/p/10822979.html