Spring重点知识学习

Spring Framework

使用spring可以轻易的创建一个企业级应用,它使用Java语言所有的企业级环境中的所有东西,spring是开源的,拥有庞大而活跃的社区来提供持续的支持.

Spring Core

spring分为多个模块,其中core为其中的一个,里面包含spring的核心技术点

IOC容器(控制反转)

IOC也被成为依赖注入,这是由一个对象定义他所依赖的关系的过程.当创建这个bean的时候也同时创建这些依赖供其使用.这样的整个过程就是反转控制的过程,比如说建房子,以前需要砖,瓦,水泥才能建造房子,如果不实用ioc时,就是自己去造砖,造瓦,然后使用.
现在使用ioc容器,只需要把砖,瓦,水泥写到清单上,ioc容器自动把这些准备好供使用,省去来自己制造的过程.

org.springframework.beansorg.springframework.context 是spring实现IOC容器的基础.BeanFactory接口是能够管理任何对象的高级的配置接口,ApplicationContext是BeanFactory的子接口.因为:

  • 更容易和Spring 的AOP特性相结合
  • 消息资源处理,用于国际化问题
  • 事件发布
  • 用于特定的上下文比如web应用程序的WebApplicationContext

简单来说就是BeanFactory提供了基本的功能,而ApplicationContext提供了更多的企业定制化的功能.

ApplicationContext代表了IOC容器,提供了初始化、配置、组装beans.通过配置元数据来获取有关初始化..等的指令.这里所指的配置元数据可以通过配置文件,注解或者java代码来实现.通过配置元数据来体现对象和其依赖.

下图为官网提供的spring工作的简化图:

IOC容器

SpringBean的生命周期

生命周期
生命周期大概包含这几个阶段:

  1. 实例化Bean对象,这时还未进行依赖注入,最后将bean加入到beanwapper中.
  2. 设置对象属性.Spring根据BeanDefinition中的信息进行依赖注入.并且通过BeanWrapper提供的设置属性的接口完成依赖注入。
  3. 注入Aware接口,检测是否是想相关Aware接口,并装配相关接口的方法.
  4. BeanPostProcessor 此时bean已经成功被构造,通过实现这个接口来自定义前置和后置的处理规则.
  5. 调用initialzingBean和int-methods,这时对象成功被初始化
  6. 最后调用disposableBean的afterpropertiesSet方法和destroy-methods来实现指定对象销毁.

Spring AOP

AOP的意思是面向切面编程,在理解面向切面前,不得不说面向对象.什么是面向对象,面向对象编程就是将事务对象化,依据对象进行层级化,面向对象通过封装继承多态的方式实现了对象层次结构,但是实际应用时可能会遇到需要横向的进行业务处理,典型的就如日志,因为在实际代码编写时,不能每次在写方法前后都加入相同的代码,这样即浪费时间,又导致代码冗余.所以面向切面编程必不可少.

AOP将多个相同的业务代码整合,形成一个通用的“切面”,通过切面可以分割出“核心关注点”“横切关注点”,核心关注点就是实际的核心业务关注的代码逻辑部分,横切关注点就是公共的代码的实现.

其中AOP中有几个比较关键的概念:

  1. 横切关注点:对哪些方法进行拦截,拦截后如何处理.这些关注点叫做横切关注点
  2. 切面:切面就是对横切关注点的抽象,就如同类对事物的抽象类似
  3. 连接点(joinpoint):被拦截到的点,可以通过连接点获取被拦截的参数等信息
  4. 切入点:连接点进行拦截的定义
  5. 织入:横切的过程叫做织入

简单的代码实现(注解)

下面代码使用注解的方式实现的Spring AOP,配置文件同理,需要配置切面(主要是切点和通知方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Component
// 标志为AOP @Aspect
public class ServiceLog {
private Logger logger = LoggerFactory.getLogger(ServiceLog.class);

@Autowired
HttpSession httpSession;

// 前置通知 切入点前执行
@Before("execution(* com.nanyin.jreact.service.serviceImpl..*.*(..))")
public void handelServiceMethodBefore(JoinPoint joinpoint){ //JoinPoint 为连接点,通过连接点可获取参数等
try{
String username = (String) httpSession.getAttribute("user");
BaseUtil.setUser(Optional.ofNullable(username).orElse("空 "));
}catch (Exception e){
e.printStackTrace();
}
}
// 后置通知 切入点后执行
@After("execution(* com.nanyin.jreact.service.serviceImpl..*.*(..))")
public void handelServiceMethodAfter(JoinPoint joinpoint){
try{
String username = (String) httpSession.getAttribute("user");
BaseUtil.setUser(Optional.ofNullable(username).orElse("空 "));
}catch (Exception e){
e.printStackTrace();
}
}
}

JDK动态代理和CGLIB代理

两者都可以实现AOP代理功能,但是jdk代理需要代理类和委托类都实现系统的接口,但是实际应用的时候这种情况非常少,这时候会自动使用CGLIB实现动态代理

Spring事务管理

事务包含四个基本特性,也就是常说的ACID,分别为原子性,一致性,隔离性,持久性

事务的接口

  1. PlatformTransactionManager: (平台)事务管理器

spring 不直接管理事务,而是实现不同的事务管理器,将事务交给框架处理,如为ibaits 和 hibernate 有不同的实现.

1
2
3
4
5
6
<!-- 事务管理器 xml 配置 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
  1. TransactionDefinition: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
1
2
3
4
5
6
7
8
9
10
11
12
public interface TransactionDefinition {
// 返回事务的传播行为
int getPropagationBehavior();
// 返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据
int getIsolationLevel();
//返回事务的名字
String getName()
// 返回事务必须在多少秒内完成
int getTimeout();
// 返回是否优化为只读事务。
boolean isReadOnly();
}
  1. TransactionStatus: 用来记录事务运行状态
1
2
3
4
5
6
7
public interface TransactionStatus{
boolean isNewTransaction(); // 是否是新的事物
boolean hasSavepoint(); // 是否有恢复点
void setRollbackOnly(); // 设置为只回滚
boolean isRollbackOnly(); // 是否为只回滚
boolean isCompleted; // 是否已完成
}

自定义注解

构造注解

注解使用@interface来标识为一个注解,具体使用可以参考如下:

1
2
3
4
5
6
7
8
9
10
11
// @Target原注解的意义是表明作用域,比如type就是表示要标注到类接口上
@Target({ElementType.TYPE})
// 表示作用域
@Retention(RetentionPolicy.RUNTIME)
// 表明其他注解能够继承该注解
@Inherited
// javadoc会包含
@Documented
public @interface TableDescription {
String description();
}

其中该注解的作用就是1.标注在类接口上2.作用在运行时,能够通过反射得到接口中的内容3.能够让其他注解继承该注解4.能够生成javaddoc文档

下面来重点关注第一个和第二个元注解:

  1. @Target是这个注解的作用域,ElementType.METHOD是这个注解的作用域的列表,METHOD是方法声明,除此之外,还有:CONSTRUCTOR(构造方法声明),FIELD(字段声明),LOCAL VARIABLE(局部变量声明),METHOD(方法声明),PACKAGE(包声明),PARAMETER(参数声明),TYPE(类接口)
  2. @Retention是它的生命周期,前面不是说注解按照运行机制有一个分类嘛,RUNTIME就是在运行时存在,可以通过反射读取。除此之外,还有: SOURCE(只在源码显示,编译时丢弃),CLASS(编译时记录到class中,运行时忽略),RUNTIME(运行时存在,可以通过反射读取)

如何使用自定义注解

  • 添加注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entity
@Data
@Table(name = "person")
// 这里使用到了上面的自定义注解TableDescription
@TableDescription(description = "this is person table")
public class Person {
@Id
private long id;
@Column(name = "name",length = 128)
private String name;

@Column(name = "age",length = 3)
private short age;
}
  • 获得注解内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void testAnn(){
try{
// 反射获取类
Class clazz = Class.forName("com.nanyin.jreact.entry.Person");
Boolean exist = clazz.isAnnotationPresent(TableDescription.class);
if(exist){
//如果注解在类中存在
TableDescription tableDescription = (TableDescription) clazz.getAnnotation(TableDescription.class);
// 获得注解内容
System.out.println(tableDescription.description());
}
}catch (ClassNotFoundException c){

}
}

上面只是简单的掩饰注解的用法,但实际上业务会比这难上许多.

springMVC 工作流程

先上一张图:来自https://www.cnblogs.com/xiaoxi/p/6164383.html
SpringMvc工作原理

由图中可以看到SpringMvc中最重要的起到中枢的是DispatcherServlet(前端控制器).

  1. 在DispatcherServlet接受到客户端请求后,使用 handlerMapping 进行映射处理.在生成处理器映射器之后, 返回一个handler,如果有拦截器的化还生成拦截器.交给 DispatcherServlet 进行下一步处理.
  2. 第二步交给 handlerAdatper (处理器适器) HandlerAdapter 经过适配调用具体的处理器( Controller ,也叫后端控制器)。Controller执行完成返回ModelAndView。
  3. 第三步,DispatcherServlet将最终的结果交给 viewResolver 试图解析器进行视图解析
  4. DispatcherServlet 根据返回的view进行视图渲染,最终返回给客户端用户.
-------------本文结束感谢您的阅读-------------

本文标题:Spring重点知识学习

文章作者:NanYin

发布时间:2019年05月05日 - 12:05

最后更新:2019年08月12日 - 13:08

原始链接:https://nanyiniu.github.io/2019/05/05/2019-05-05-Spring_Framework%E9%87%8D%E7%82%B9%E5%AD%A6%E4%B9%A0/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。