关于Spring的那点事


一.Spring约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//上面两个是基础IOC的约束,必备
xmlns:context="http://www.springframework.org/schema/context"
//上面一个是开启注解管理Bean对象的约束
xmlns:aop="http://www.springframework.org/schema/aop"
// aop的注解约束
xmlns:tx="http://www.springframework.org/schema/tx"
// 事务的约束
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
// 上面两个是基础IOC的约束,必备
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
//上面一个是开启注解管理Bean对象的约束
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
//aop的注解约束
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
//事务的约束
default-autowire="byName" default-lazy-init="false">

结论:不要在Spring的配置里,配置上XSD的版本号,因为如果没有配置版本号,取的就是当前jar里的XSD文件,减少了各种风险。而且这样约定大于配置的方式很优雅。

14.spring的生命周期
如果从大体上区分值分只为四个阶段
a.BeanFactoyPostProcessor实例化
b.Bean实例化,然后通过某些BeanFactoyPostProcessor来进行依赖注入
c.BeanPostProcessor的调用.Spring内置的BeanPostProcessor负责调用Bean实现的接口: BeanNameAware, BeanFactoryAware, ApplicationContextAware等等,
这些内置的BeanPostProcessor调用完后才会调用自己配置的BeanPostProcessor
d.Bean销毁阶段

二.IOC(控制反转)

在类和类之间存在控制权,控制权指的是对象的创建和使用。就是由spring来负责控制对象的生命周期和对象间的关系。
比如:有类A和类B,之前的做法是在A中调用B,那么控制权就在A中,这样做的耦合度较高,如果修改了B,A也要做相应修改。
引入Spring框架后,控制权由Spring容器来负责。当A想使用B时,需要由Spirng容器通过 配置文件迚行注入。
这种思想就是IoC(为了更好的理解,可以这样认为,对象创建和使用 的控制权转移到了Spring容器,由Spring容器来控制)。
用setter方法,然后在配置文件中指定依赖关系。好比现实生活中的中介。比如:找工作需要中介服务商。
底层原理就是Java反射。反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
在Spring中,默认情况下是使用java动态代理技术来实现,当需要代理的类不是接口类型的时候,Spring会自动切换为CGLIB来进行代理。

容器是spring的核心,使IoC管理所有和组件
spring的两种容器:a、BeanFactoy,b、ApplicationContext应用上下文
BeanFactory:BeanhFactory使用延迟加载所有的Bean,为了从BeanhFactory得到一个Bean,只要调用getBean()方法,就能获得Bean

ApplicationContext:a、提供文本信息解析,支持I18N
b、提供载入文件资源的通用方法
c、向注册为监听器的Bean发送事件
d、ApplicationContext接口扩展BeanFactory接口
e、ApplicationContext提供附加功能
5、ApplicationContext的三个实现类:a、ClassPathXmlApplication:把上下文文件当成类路径资源
b、FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息

6、在默认情况下,Bean全都是单态,在<bean>中的singleton为false
7、<bean>中的id属性必须遵循Java规范,而name属性可以不遵循
8、Bean的实例化的时候需要一些初始化的动作,同样当不再使用的时候,需要从容器中将其销毁
9、对象的初始化:<bean init-method="方法名">
10、对象的销毁:<bean destroy-method="方法名">
销毁对象的过程:a、主线程先被中断
b、Java虚拟机使用垃圾回收机制回收Bean对象
11、Bean设置:设值注入:1)简单配置:<bean id="xxx" class="Bean的全称类名">
        <property name="xx" value="xxxxx"></property>
      </bean>
value中的值可以是基本数据类型或者String类型,spring将会自动判断设置的类型并且将其转换成合适的值
2)引用配置:<bean id="xxx" class="Bean的全称类名">
     <property name="xx" ref="xxxxx"></property>
   </bean>
ref中的值是引用数据类型,spring容器会完成获取工作
3)List和数组:<bean id="xxx" class="Bean的全称类名">
<property name="list">
<list>
<value></value>
<ref bean=""/>
</list>
</property>
</bean>
list元素内可以是任何元素,但不能违背Bean所需要的对象类型
4)Set配置:和<list>一样,将<list>改成<set>
5)Map配置:Map中的每条数据是由一个键和一个值组成,用<entry>元素来定义
<bean id="xxx" class="Bean的全称类名">
<property name="list">
<entry key="key1">
<value></value>
</entry>
</property>
</bean>
<bean id="xxx" class="Bean的全称类名">
<property name="list">
<entry key="key1">
<ref bean=""/>
</entry>
</property>
</bean>
注意:配置entry时,属性key的值只能是String,因为Map通常用String作为主键
6)Properties配置:使用<props>和<map>相似,最大区别是<prop>的值都是String
注意:使用设值注入必须要有set方法,通过name属性找set方法
优势:a、通过set()方法设定更直观,更自然
b、当依赖关系较复杂时,使用set()方法更清晰
构造子注入:必须要有无参和带参的构造方法,加上index(值从0开始)属性避免注入混淆
<constractor-arg>
注意:设值注入可以和构造子注入混合使用。先调用构造方法产生对象,再调用set()方法赋值。但只使用设值注入时,会先调用无参的构造方法
优势:a、依赖关系一次性设定,对外不准修改
b、无需关心方式
c、注入有先后顺序,防止注入失败

Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,
另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,
提供了更多的额外功能。二者对Bean的初始化也有很大区别。BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。
而ApplicationContext 在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean ,直接为应用程序服务。
相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,
并自动将它们注册到应用上下文中;而BeanFactory需要在代码中通过手工调用addBeanPostProcessor()方法进行注册。

Bean装配实际上就是让容器知道程序中都有哪些Bean,可以通过以下两种方式实现:
配置文件(最为常用,体现了依赖注入DI的思想)
编程方式(写的过程中向BeanFactory去注册)


作用:

1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
c. 事件传递:通过实现ApplicationContextAware接口
3. 常用的获取ApplicationContext的方法:
FileSystemXmlApplicationContext:从文件系统或者url指定的xml配置文件创建,参数为配置文件名或文件名数组
ClassPathXmlApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件
WebApplicationContextUtils:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
这两种方式都默认配置文件为web-inf/applicationContext.xml,也可使用context-param指定配置文件
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>

三.AOP(面向切面)

为什么要用AOP?
面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。
这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
但是在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,就必须在两个类的方法中都加入日志的内容。
也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
也许有人会说,那好办啊,可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。
那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?

什么是AOP?
这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
一般而言,管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。
有了AOP,就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
jdk动态代理的缺陷是:它只能代理接口,而不能没有代理没有接口的类。

Spring的bean就相当于定义一个组件,这个组件是用于具体实现某个功能的。
这里的所定义的bean就相当于给了一个简洁方便的方法来调用这个组件实现要完成的功能。
对于Spring最主要的应该就是由这些bean组成的bean工厂,每个bean实现一个功能。

其他的属性:
Id:标识该bean的名称,通过factory.getBean(“id”)来获得实例。
Class:该bean的类路径。
Singleton:默认为true,即单实例模式,每次getBean(“id”)时获取的都是同一个实例,如果设置为false,即原型模式,则每次获取的是新创建的实例。
Init-method:在bean实例化后要调用的方法(bean里定义好的方法)。
Destroy-method:bean从容器里删除之前要调用的方法。
Autowire:其属性要通过何种方法进行属性的自动装配。
对于上述的各个属性,id和class是必要的,其他的则可以省略。例如如果设置了autowire的值,则表明需要自动装配,否则是手动装配。

一般而言,使用Spring框架的主要作用: 会使用IOC整合组件(各种Bean),使用AOP来管理事务。

AOP有2种:基于xml配置文件方式:1.定义切面;2.声明切入点;3.应用通知。
注解方式:1.在配置文件中启用对切面的注解;2.在切面类中用注解来定义切面,声明切入和应用切面。

使用场景

事务管理:
a.使用声明书事务管理:
b.使用编程式事务管理:编程式即采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config/>,其作用是开启注解的方式。

类头的@Transactional为默认事务配置,如方法没有自己的事务类型,则按默认事务,如有自己的配置,则按自己的配置。

spring只是控制数据库的事务提交和回滚,借助于java的反射机制,在事务控制的方法(通常是service层的方法)前后获取事务开启session,
然后执行数据操作,如果方法内有异常被抛出,spring会捕获异常并回滚在这个方法内所有的数据操作,如果成功则提交所有的数据,最后spring会帮关闭需要关闭的东西。
所以spring想要做的是,要程序员专注于写逻辑,不需要关系数据库何时开启和关闭连接。

Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,
无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、 TransactionManager这两部分只是会根据数据访问方式有所变化,
比如使用Hibernate进行数据访问时,DataSource实际为 SessionFactory,TransactionManager的实现为HibernateTransactionManager。

猜你喜欢

转载自www.cnblogs.com/ZJOE80/p/10194769.html
今日推荐