Spring小笔记2

1、Spring是什么?

         Spring是一个开源的轻量级的Java开发框架,以IOC(控制翻转)和AOP(依赖注入)为内核,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。

主要由以下几个模块组成:

Spring Core:核心类库,提供IOC服务;

Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);

Spring AOP:AOP服务;

Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;

Spring ORM:对现有的ORM框架的支持;

Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;

Spring MVC:提供面向Web应用的Model-View-Controller实现。

2、Spring 的优点?

  (1)spring属于低侵入式设计,代码的污染极低;

  (2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;

  (3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。

  (4)方便集成各种框架(如mybatis,hibernate,Quartz)。

  (5)方便程序测试(提供对junit4的支持,通过注解方便的使用程序)

  (6)支持声明式事务处理;

  (7)降低了javaEEApI的使用难度(对jdbc,和javaMail提供了封装)

Spring的两大核心容器BeanFactory和ApplicationContext

1、BeanFactory方式创建

BeanFactory通过其接口的主要实现类XmlBeanFactory创建容器;该方式不多见

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource(":application.xml"));

2、ApplicationContext方式创建

1、通过 new ClassPathXmlApplicationContext("application.xml");的方式获取一个applicationContext对象

ApplicationContext   applicationContext  = new ClassPathXmlApplicationContext("application.xml");

2、通过FileSystemXmlApplicationContent("d:application.xml");这种方式也能创建,但是默认使用的绝对路径,使程序灵活性变差,不推荐使用;

ApplicationContext   applicationContext  = new FileSystemXmlApplicationContent("d:application.xml");

获取配置文件中的bean:

通过applicationContext.get("beanName");

BeanFactory和ApplicationContext有什么区别?

ApplicationContext 是 BeanFactory的子接口;

ApplicationContext包含了BeanFactory功能之外,还扩展了国际化,资源访问,事件传播等支持;

都是通过xml的方式加载bean;

BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。

ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。

BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

依赖注入IOC(简称DI)

(1)IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。

(2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。

Bean的实例化

Spring的IOC有多种种注入方式,参考https://www.cnblogs.com/lzghyh/p/12580674.html

通过xml的方式注入时,定义bean的几个常用属性:

id:bean的唯一标志

name:bean的名称,多个名称可以使用逗号分隔

class:指定bean的具体实现类,使用全限定名

property:用于对属性赋值,也可通过其注入其他的bean

ref:用于指定bean的名称或id,辅助注入bean

如果未指定id和name,那么spring会将class当做id使用。

Bean的作用域

bean的作用域是通过scope属性来指定的;例如

<bean id= 'scope' class='com.item.Scope' scope='prototype'>

(1)singleton:默认,每个容器中只有 一个bean的实例,单例的模式由BeanFactory自身来维护。

(2)prototype:为每一个bean请求提供一个实例。

(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。

(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

(6)application:为每一个ServletContext对象创建一个实例,仅在web相关的ApplicationContext 中生效

(7)websocket:为每一个websocket对象创建一个实例,仅在web相关的ApplicationContext 中生效

Bean的生命周期:

 首先说一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;

1、实例化bean

2、利用依赖注入完成Bean中所有属性的注入

3、处理Aware接口:

  ①、如果bean实现了BeanNameAware接口,这spring调用setBeanName()方法传入当前bean的id

  ②、如果bean实现了BeanFactoryAware接口,这spring调用setBeanFactory()方法传入当前工厂实例的引用

  ③、如果bean实现了ApplicationContextAware接口,这spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用

4、如果BeanPostProcessor(预加载方法)和bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialization(Object obj, String s),Spring的AOP就是它实现的;

5、InitializingBean 与 init-method:

  如果bean实现了InitializingBean 接口,则spring将调用afterPropertiesSet()方法;

  如果配置文件配置了 init-method 属性,则会自动调用其配置的初始化方法。

6、如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

7、如果bean实现了DisposableBean接口:

当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

8、如果指定了bean的作用范围为:scope=‘singleton’,这创建的bean将被刚入spring ioc缓冲池中,触发bean生命周期管理,如果定义了scope=‘prototype’,则调用者拥有该bean的生命周期,spring不在管理;

SpringAOP: 

AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。

AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。

(1)AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。

(2)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:

    ①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例,  生成目标类的代理对象。

 ②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

(3)静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。

InvocationHandler 的 invoke(Object  proxy,Method  method,Object[] args):proxy是最终生成的代理实例;  
 method 是被代理目标实例的某个具体方法;  args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。

Spring提供了操作JDBC的模板:JdbcTemplate

Spring的事务

PlatformTranscationManager接口是spring提供的平台事务管理器;

其主要实现类DataSourceTransationManager用于配置JDBC的事务管理器,事务的隔离级别默认使用数据库的;

(1)Spring事务的种类:

spring支持编程式事务管理和声明式事务管理两种方式:

  ①编程式事务管理使用TransactionTemplate。

  ②声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中。

声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式,使业务代码不受污染,只要加上注解就可以获得完全的事务支持。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

(2)spring的事务传播行为:

spring事务的传播行为说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。

① propagation_required:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
② propagation_supports:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
③ propagation_mandatory:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ propagation_requires_new:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ propagation_never:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按required属性执行。

(3)Spring中的隔离级别:

① isolation_default:这是个 platfromtransactionmanager 默认的隔离级别,使用数据库默认的事务隔离级别。
② isolation_read_uncommitted:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
③ isolation_read_committed:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
④ isolation_repeatable_read:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
⑤ isolation_serializable:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。
原文地址:https://www.cnblogs.com/lzghyh/p/12622871.html