Spring(一)

一. Spring引言

1.Spring框架

开源的、轻量级的JavaEE解决方案,是众多优秀的设计模式组合。轻量级:代码侵入性小。
Spring框架用来管理(创建|使用|销毁)项目中的组件,由于Spring框架可以帮我们生产项目中组件对象,因此也习惯成Spring是一个工厂或者Spring容器。
Spring框架中使用了众多优秀的设计模式,包括工厂模式动态代理模式、装饰器模式等

2.工厂模式

通过工厂类,完成一个对象的创建或者生产。

工厂类

通过反射技术完成创建所需对象

3.Spring核心API

ApplicationContext 接口(工厂类)生产创建对象+xml文件

接口的实现类:

  • ClassPathXMLApplicationContext //利用类路径的xml文件来载入Bean定义的信息
  • WebXmlApplicationContext 利用web环境下xml文件
  • FileSystemXmlApplicationContext:利用文件系统中的xml文件来载入Bean

工厂类是重量级资源,内存占用大,功能多一个应用只能应该创建一个

二. Spring核心–IOC

1.Bean的创建模式

<bean id="" class="" scope="singleton|prototype"></bean>
  • singleton:单例模式(默认),Spring工厂只创建一个对象
  • prototype:多例模式,每次调用工厂都会创建新的对象

2.IOC和DI

IOC控制反转

IOC是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

类比Servlet:不需要程序员创建它的实例,调用service方法,它的生命周期由tomcat来控制,因此可以说Servlet的控制权被交出去了。Tomcat容器也被称为Servlet容器,由容器来负责创建它的实例,调用它的初始化销毁及service方法。

控制反转:将对象的创建由原来(new)的方式转移到配置文件中,交给Spring工厂来创建。原理:工厂模式+反射

Spring容器与Servlet容器的区别:

  • Servlet容器只能运行Servlet、jsp
  • Spring 容器:不依赖服务器,可以独立运行,普通Java类就可以运行,统称为bean

DI依赖注入

Spring不仅要创建对象,还有创建类与类之间的关系,因此在IOC的基础上又提出了DI的思想

依赖:一个类的实例对象需要使用另一个类的实例,通常会将依赖对象做成成员变量

注入:在Spring配置文件中给对象的属性进行自动赋值

三. Spring注入方式

set注入

底层调用类的set方法为属性赋值

  • 八种基本类型+String+日期类型
  • 引用类型注入
<bean id="personDao" class=""></bean>
<bean id="personService" class="xxxx">
   <property name="personDao" ref="personDao"></property>
</bean>
  • 数组
<property name="array">
   <array>
     <value>xxx</value>
     <value>xxx</value>
     xxxx
  </array>
</property>
  • set集合
<property name="set">
   <set>
     <value>xxx</value>
     <value>xxx</value>
     xxxx
  </set>
</property>
  • list集合
<property name="list">
   <list>
     <value>xxx</value>
     <value>xxx</value>
     xxxx
     <!--引用类型-->
     <ref bean="bean-name"/>
  </list>
</property>
  • Map集合
<property name="map">
   <map>
     <entry key="key" value="value"/>
     <!--引用类型-->
     <entry key-ref="bean-name" value-ref="bean-name"/>
     xxxx
  </map>
</property>
  • Properties类型等价于Map<String,String>
<property name="props">
   <props>
     <prop key="xxx">xxxxx</prop>
     xxxx
  </props>
</property>

构造注入

使用构造方法完成成员变量的赋值

构造注入

自动注入

根据注入的属性名与配置文件中bean的id匹配,一致则注入,不一致报错

<bean id="student" class="xxx.Student" autowire="byName"/>

根据注入的属性类型,与配置文件中的类型匹配,类型一致注入(在多个实现类时,会产生歧义)

<bean id="student" class="xxx.Student" autowire="byType"/>

四. Spring工厂的高级特性

1.Bean的生命周期

创建:随着工厂启动,所有单例bean随之创建,饿汉式;非单例的bean每次使用时创建,懒汉式

销毁:工厂关闭时(调用close方法),Spring销毁所有创建出来的单例bean对象。Spring对多例bean管理松散,不会负责多例bean的销毁

2.生命周期相关方法

初始化方法:用户可以任意定义一个方法,为初始化方法,那么这个方法,会在对象创建之后,被Spring调用执行。

销毁方法:用户可以任意定义一个方法为销毁方法,Spring会在这个对象销毁之前,调用销毁方法

<bean id="xxx" class="xxxxx" init-method="自定义的初始化方法" destroy-method="自定义的销毁方法"/>

3.FactoryBean技术

1.Spring工厂创建对象

  • 简单对象:可以通过构造方法创建的对象通过set注入、构造注入、自动注入
  • 复杂对象:不能通过构造方法创建,创建过程中需要经历多个步骤,例如:Connection SQLSessionFactory 接口对象

2.如何创建复杂对象

实现FactoryBean接口,泛型为需要创建的对象

public class ConnectionFactoryBean implements FactoryBean{
    getObject:复杂对象的创建代码实现
    getObjectType:返回复杂对象的Class
    isSingleton:   true--单例模式  false--多例模式
    
}
创建session连接

在Spring中配置

<bean id="conn" class="factoryBean.ConnectionFactoryBean"></bean>

使用

Spring中配置的类为FactoryBean的实现类时,创建的不是类本身的对象而是类中getObject创建的复杂对象,isSingLetion方法的返回值由原对象本身的特性决定;如果必须创建FactoryBean的实现类对象时使用ctx.getBean(“&id”)

五. Spring核心–AOP

AOP面向对象编程:以对象为基本单位的程序开发,通过对象之间彼此协同,相互调用,完成程序的构建。Spring使用AOP 为目标类生成代理对象,为目标类中的方法添加某些额外功能,进行增强处理。

  • 目标类:核心功能,被代理的类;
  • 增强处理:额外功能,通过通知(advice)进行添,加
  • 切入点:标记了一个位置(需要做增强处理的地方)通过aop:pointcut标签配置切入点,一般都是配置在service层
  • 切面:把通知放置在切入点位置之后,形成的一个平面(几何概念)

额外功能—通知

额外功能是由Advice的子接口完成具体开发,又称为通知

  • MethodBeforeAdvice 前置通知 ,在目标方法执行前执行
  • AfterReturningAdvice 后置通知 ,在目标方法执行之后执行
  • MethodInterceptor 环绕通知需要返回值
环绕通知
  • ThrowsAdvice 异常通知,是标记接口

切入点表达式

<aop:config>
	<aop:pointcut expression="execution(* *(..))" id="pc"/>
    <aop:advisor advice-ref="xxxAdvice" poincut-ref="pc"/>
</aop:config>

execution()函数:精确到方法级,切入点表达式中,可以通过运算符表达更复杂的内容

切入点表达式

还有其他方式:within()函数:精确到类级;args函数:通过目标方法的参数来匹配;不过为了不必要功能,所以建议精确到方法级别。

切面执行顺序

切面:切入点+通知(额外功能)。多个切面按照指定顺序配置,在aop:advisor中通过order属性值(int 值)来指定,值越小越优先,当前切面中存在order属性时,以order属性值为主,没有order属性或者order属性相同时,以配置顺序为主。

六. 代理模式

Spring动态代理生产相应对象,Spring中生成代理对象用两种方式:

1.使用JDK代理:Proxy基于接口生成代理对象,通过实现和目标类相同的接口,代理对象只能赋值给接口的引用(Spring默认使用JDK方式)

2.基于继承生成代理对象Spring CGLIB,通过继承实现目标类,代理对象即可赋值给接口引用,也可以赋值给实现类引用

可以在Spring配置文件中切换默认生产代理的方式:

<aop:config proxy-target-class="true|false">xxxx</aop:config>
true:使用目标类生成代理(CGLIB)
false:使用JDK的Proxy接口生成代理

代理对象的生产过程

为什么通过id得到的是代理对象,而不是目标对象本身?

生产代理对象

目标对象创建出来之后,因为里面的方法符合切入点表达式的规则,就会交给BeanPostProcessor后置处理,处理完成之后生成代理对象又交个Spring容器管理