zoukankan      html  css  js  c++  java
  • Spring

    IoC

    一 Spring概述

    1.什么是Spring?

    • Spring是为了解决企业应用开发的复杂性而创建的,优秀的轻量级企业应用解决方案,开放源代码,主要特点是采用分层结构,允许单独使用某一模块,也可以将多个模块组合使用。
    • 企业应用:为了满足企业运行需要开发的软件系统,现在的企业应用大多运行在开放性平台(存在信息交互的可能性),不再是孤立的系统,而是在相互联系中构成了一个系统群。
    • 轻量级:轻量级框架如Struts、Spring,侧重于降低开发的复杂度,体积小,消耗小,相应地处理能力有所减弱。
    • JavaBean:使用java语言编写的可重用组件,主要用作数据的载体。
    • EJB:Enterprise  JavaBean,服务器端组件模型,定义了一个用于开发基于组件的企业应用的规范,本身复杂而繁琐。

    2.Spring的技术基础

    • IoC:Inversion of  Control,控制翻转。
    • AOP:Aspect  Oriented  Program,面向切面编程。

    3.Spring的构成

    • Spring core:Spring框架的核心,提供了Spring框架的基础功能,实现了IoC,包含重要的类BeanFactory。BeanFactory是IoC的容器,负责bean的实例化、初始化、使用与销毁。
    • Spring context:继承了BeanFactory,添加了许多功能,如国际化、数据校验等。
    • Spring AOP:继承AOP的所用功能,通过事务可以将Spring管理的任意对象AOP化。
    • Spring DAO:提供了JDBC的抽象层,简化了数据库厂商的异常错误,大幅度减少了代码,并且支持声明式事务与编程式事务。
    • Spring ORM:兼容所有流行的ORM框架,完美地整合了HibernateMybatis。
    • Spring Web:提供了Servlet监听器上下文与Web上下文,集成了现有的Web框架,如JSP、Struts。
    • Spring MVC:建立在Spring的核心功能之上,具有Spring框架的所有特性。

    二 BeanFactory

    1.BeanFactory

    一个容器,通过读取bean的定义文件获取所有的bean对象,实现对bean的创建、使用与管理。

    2.ApplicationContext

    继承了BeanFactory,添加了许多功能,如国际化、数据验证等,有三个比较重要的实现类:

    • ClassPathXmlApplicationContext:从类路径下加载配置文件,一般常用此类加载applicationContext.xml。
    • FileSystemXmlApplicationContext:从文件路径加载文件,适用性范围广。
    • WebApplicationContext:Spring与Web整合后在bean在Web中的容器。

    三 控制反转

    1.什么是控制反转?

    一种思想,依赖注入是该思想的一种实现,将创建实例的任务交给IoC容器,需要实例时向容器发送请求即可,这样降低了引用类A对被引用类B的依赖,即B发生改变,A需要修改很少一部分,甚至不需要修改。

    2.降低耦合度的实现过程

    在传统开发中,A类调用B类,就必须在内部创建B类,B b= new B(),当B类被删除,就需要修改A类的代码,这样A类就受到B类变化的拖累。如果A类调用的是B类的接口,并且对象由外部创建,当外部实现类发生改变时,只要提供一个满足要求的实现类,A依然可以正常运行,不需要修改A中的代码,B的变化没有波及A。

    3.依赖注入

    ⑴setter注入

    底层调用setter方法实现注入:

    <bean id="引用变量"class="全限定性类名">
          <property name="属性名">
                 <value>属性值</value>
          </property>
    </bean>

    ⑵构造器注入

    底层调用构造方法实现注入:

    1 <bean id="引用变量"class="全限定性类名">
    2       <constructor-arg>
    3           <value>参数值</value>
    4       </constructor-arg>
    5 </bean>

    配置文件中标签的赋值顺序必须与构造方法形参定义顺序一致,否则抛出出错。为了避免顺序不一致导致的错误,在配置文件中为每一个赋值标签设定一个index值,对应其要赋值的形参在构造器中的顺序:

    1 <constructor-arg index="0">
    2     <value>参数值</value>
    3 <constructor-arg>、

    ⑶集合注入

    数组与List集合: 

    1 <list>
    2      <value>value01</value>
    4      <value>value02</value>
    5 </list>

    数组还有一种更简单的赋值方式,值写在一块,用逗号隔开:

    1 <property name=""value="value01,value02"/>

    Set集合:

    1 <set>
    2     <value>value01</value>
    3     <value>value02</value>
    4 </set>

    Map集合:

     <map>
    2     <entry key=""value=""/>
    3     <entry key=""value=""/>
    4 </map>

    Properties对象:  

    1  <props>
    3       <prop key="xxx"></prop>
    5       <prop key="xxx"></prop>
    7 </props>

    ⑷引用bean   

    <property name="">
          <ref local="id"/>
    </property>

    ⑸自动装配

    byName:通过名称装配,将IoC容器中与属性名同名的bean注入。

    <bean autowire="byName"id=""class=""/>
    • 按名称装配的不足:如果IoC容器中存在多个同名而类型不同的bean,注入后就会发生错误。

    byType:将与属性数据相同的bean注入。

    <bean autowire="byType"id=""class=""/>
    • 按类型转配的不足:如果IoC容器中存在多个类型相同的bean,IoC容器会因为无法识别需要的bean而报错。

    ⑹内部bean

    如果希望内部bean只能通过外部bean访问,那么将内部bean的定义放在外部bean内部:

    <bean id="xxx"class="OuterClass">
         <property name="innerClassAttrName">
              <bean class="InnerClass">//因为不支持外部对象引用,所以不需要定义id
                    <property name="">xxxxx</property>
              </bean>
         </property>
    </bean>

    四 同类抽象bean与异类抽象bean

    1.背景

    在配置文件中,如果多个bean拥有共同的属性,分别为每一个bean配置,数据冗余,为了消除冗余,将这些共同的属性提取出来,定义在一个抽象bean中,其他bean通过引用该抽象bean为属性赋值。

    2.同类抽象bean

    为同类的bean赋值:

    <bean id="abstractBean"class="ClassA"abstract="true">
          <property  name=""value=""/>
         ........为共同属性赋值..........
    </bean>
    <bean id="xxx"parent="abstractBean">
          <property name=""value=""/>
         ........为特有属性赋值..........
    </bean>
    • abstract="true":将该bean定义为抽象bean,防止通过getBean直接访问该bean。

    3.异类抽象bean

    为不同类型的bean赋值:

    <bean id="abstractBean"abstract="true">
          <property  name=""value=""/>
          ........为共同属性赋值..........
    </bean>
    <bean id="xxx"class=""parent="abstractBean">
         <property  name=""value=""/>
          ........为特有属性赋值..........
    </bean> 

    五 bean作用域

    1.生命周期的设定

    <bean  id=""class=""/>//采用默认值singleton
    <bean  id=""class=""singleton="true/false"/>
    <bean  id=""class=""scope="singleton/prototype"/>

    2.singleton与prototype

    • singleton:bean采用单例模式,生命周期与IoC容器相同,由IoC容器管理,每次请求返回的是同一bean对象,。
    • prototype:采用多例模式,IoC容器将对象交给使用者,由使用者管理,每一次请求获取的都是不同对象,。

    六 SpEL

    1.SpEL是什么?

    Spring  Expression Language,用于在配置文件中动态地为属性赋值,该值可以来源于容器中其他bean的属性,调用bean方法的返回值,也可是调用容器以外其他类静态方法的返回值。

    2.基本语法

    #{expression}
    • 调用容器中其他bean的属性:#{beanName.attrName}
    • 调用容器中bean的方法:#{beanId.method(arg)}
    • 调用容器以外其他类的静态方法:#{T(全限定性类名).method(arg)}

    七 bean的生命周期

    1.11个阶段

    bean的生命周期可分为11个阶段,即总共有11时机可以用来改变bean,除自定义的BeanPostProcessor适用于所有bean而单独创建外,其他的都通过bean实现相应的接口实现,如BeanNameAwareBeanFactoryAwareInitializingBeanDisposableBean等。

    2.相关的接口或者类

    ⑴在bean内部自定义控制生命周期的方法

    • 定义在setter方法执行完毕后调用的方法,该方法必须无参:
    • <bean  init-method="方法名">
    • 定义在IoC容器关闭以后调用的方法,必须无参:
    • <bean destory-method="方法名"/>

    ⑵BeanPostProcessor

    一个接口,其实现类只有在配置文件中配置之后才可以使用,由底层调用,配置时无需设定id。容器中所有的bean在初始化阶段都会调用其中的两个方法:

    • postProcessBeforeInitialization:在bean初始化完毕之前由容器调用;
    • postProcessAfterInitialization:在bean初始化完毕之后由容器调用。

    八 配置文件的分散编写

    1.平等关系

    两个配置文件各自单独存在,不存在包含关系。在java代码中读取平等关系的配置文件需要使用指定类的可变参数的形式:

    new  ClassPathXmlApplicationContext(String...)

    2.包含关系

    一个配置文件在内容上包含另一个配置文件:

    <import resources="classpath:xxxxx.xml"/>
    • 配置文件路径前一定要加classpath,为底层指定加载方式,因为配置文件的加载方法有多种:以ClassPath开头的类从类路径加载,以FileSystem开头的类从文件路径加载。在java中加载时使用ClassPath开头的类实际上已经设定了文件的加载方法,程序员只负责加载外层文件,内层文件的加载是由底层负责的,如果不指明加载方式,底层无法加载。底层执行过程大致是:提取classpath,判断,根据判断结果选择加载方式,如果classpath不存在,底层就无法进行判断,无法运行,就会抛出错误。

    九 注解式开发

    1.注册扫描器

    在配置文件中注册注册扫描器:

    <context:component-scan base-package="xxx"/>

    Spring不同于Hibernate与Struts,没有默认的配置文件,被动加载,必须显式指明配置文件,因此当采用注解开始时也必须显式指明组件位置。

    • 如果包名为xxx,表示扫描该包及其子包。
    • 如果包名为xxx.*,表示只扫描子包。

    2.常用注释:

    • @Component(value="相当于配置文件中的id"):表明该类是一个组件,扫描时容器会创建该类的实例,这是bean注解的第一步,先让容器把该类当做需要创建bean的类。作用相同的注解有@Repository(注解在Dao接口的实现类上)@Service(注解在Service的实现类上)@Controller(注解在Controller类上)。
    • @Scope(value="singleton/prototype"):设置作用域。
    • @Value(value=""):为一般属性赋值。
    • @Resource(name=""):为域属性赋值。域属性就是自定义类的对象。@Autowired::Spring提供的依照类型的域属性注入注解。
    • @PostConstruct:在bean内部设定在初始化完成之后调用的方法。初始化完成的标识是InitializingBean实现类的方法afterPropertiesSet调用完毕。
    • @PreDestroy:在bean内部设定bean销毁前调用的方法。

    十 SpringJUnit4

    SpringJUnit4提供了对bean的简化测试方案,进行简单设置之后,测试时就不需要再创建容器,可以直接使用bean:

    1. 在类上加@RunWith(SpringJUnit4ClassRunner.class):表示采用SpringJUnit4进行测试。
    2. 在类上加@ContextConfiguration(locations="classpath:xxxx.xml"):指明配置文件。
    3. 在域属性加@Autowired:按照类型注入,也可以采用其他方式注入

      AOP

    一概述

    1.产生背景

    在AOP产生以前,OOP是编程的基本原则,所有对象执行需要的代码都必须写在类中,如果多个类拥有一部分相同的代码,那么这些代码就必须在每个类中都编写,不仅代码大量重复,而且不便于维护,这时就产生了将那些重复出现、与业务无关的代码从业务中分离出来的思想,就是AOP。AOP将重复的、与业务无关的代码从业务中分离处理,业务执行时切入业务中,形式上与业务分离,执行时与业务结合,不仅便于维护,而且降低了业务逻辑部分与非业务逻辑部分的耦合度。

    2.原理

    Aspect Oriented Program,面向切面编程,建立在动态代理机制之上。

    3.重要的概念

    • 切面:对象执行过程中切入流程的、与业务逻辑无关的代码。在程序中,切面是一个集中了通知的类。
    • 切入点:切面切入流程的点,Spring只支持方法类型的切入点,即切面只能在对象方法执行前后切入,不能切入方法内部。
    • 通知:切入点被横切时,所采取的业务逻辑,通知是切面中的方法。
    • 目标对象:切面切入的对象。
    • 织入:将切面功能应用于目标对象的过程。
    • 引用:动态地向目标对象添加属性与方法的过程。

    二 Spring自身对AOP的实现

    1.原理

    Spring自身提供了对AOP思想的实现,主要借助内置接口的实现类与配置文件完成。

    2.Advice

    通知,切入点被横切时采取的处理逻辑,即在切入点前后执行的方法。在Spring中,Advice是一个层级比较高的接口,具体使用的通知都间接实现了该接口。缺点是,一旦定义就对所有方法都起作用。

    • 前置通知:在切点执行前执行,实现MethodBeforeAdvice实现。
    • 后置通知:在切点成功执行后执行,排在环绕通知之后,方法无返回值,不可以修改返回值,实现AfterReturningAdvice。
    • 环绕通知:在切点执行前与执行成功后执行,可以修改返回值,实现MethodInterceptor。
    • 异常通知:在切点抛出异常时,执行,实现ThrowsAdvice。

    3.Advisor

    顾问,Advice的装饰者,可以对方法进行筛选,使通知只对选定的方法起作用。常用到的两个实现类:

    • NameMatchMethodPointcutAdvisor:列举选定的方法,使通知只对选定的方法有效。
    • RegexMethodPointccutAdvisor:通过正则表达式匹配方法。

    ⑴NameMatchMethodPointcutAdvisor

    <bean id=""class="Advisor的两个实现类其中一个">
           <property name="advice"ref="通知名"/>//装饰的通知
           <property name="mappedNames"value="方法名"/>//即切点
    </bean>

    ⑵RegexpMethodPointcutAdvisor

    <property name="advice"ref="通知名" />
    <property name="pattern" value="正则表达式,匹配对象时接口的方法" />

    4.ProxyFactoryBean

    ⑴代理通过ProxyFactoryBean类创建,底层执行Proxy.newProxyInstance(),对比底层实现为该类属性赋值,动态地执行:

    <bean id=""class="xxxxxx.ProxyFactoryBean">
             <property name="targetName"name=""/>
             <property name="interceptorNames"value="通知名或顾问名"/>
    </bean>

    5.基于顾问的自动代理生成器

    当有多个目标对象时,使用ProxyFactoryBean创建代理对象时,需要为每一个代理对象编写创建过程,而使用DefaultAdvisorProxyCreator,可以自动为目标对象创建代理。因为DefaultAutoProxyCreator底层实现了BeanPostProcessor,由底层自动调用。

    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    6.基于beanName的自动代理生成器

    ⑴该代理生成器弥补了基于顾问的代理生成器无法选择通知、无法选择目标对象的不足。

    <bean id="proxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
             <property name="beanNames" value="target" />//选择要代理的对象
             <property name="interceptorNames" value="methodInterceptor" />//选择切面
    </bean>

    7.获取代理

    无论是基于顾问的,还是基于beanName的自动代理生成器,都可以同时代理多个目标对象,为了区分被代理的目标对象只能通过目标对象来获取代理对象,这样才能保证一个代理对象指向一个目标对象。

    三 AspectJ

    <aop:config proxy-target-class="true/false">
          <aop:aspect ref="切面所在类的id">
                 ---将切点定义在切面内,对其他切面不可见。也可以将切点定义在切面外,对所有切面可见---
                     <aop:pointcut ref="切点所在类的id" expression="execution(切入点表达式)"/>
                     <aop:before method="方法名"pointcut-ref="切点id"/>
                     <aop:after method="方法名"pointcut-ref="切点id"/>
          </aop:aspect>
    </aop:config>

    1.切入点表达式

    用于限制切入点的表达式,与表达式匹配的方法都可以用作切入点,语法格式

    [访问权限] 返回值类型 [全限定性类名] 方法名(..)
    • ():匹配不带参数的方法。
    • (*):匹配带一个参数的方法。
    • (..):匹配带任意形式参数或不带参数的方法。
    • *:代表若干字符。
    • ..:代表多级目录。
    • +:代表该类及其子类。

    2.其他标签

    • <aop:config>:配置AOP的全部信息,包括切面、切点。proxy-target-class指明所用的代理机制,CGLIB,还是基于接口的代理JDK,默认为false,使用基于接口的代理。
    • <aop:aspect>:配置切面,包含切点前执行的方法、切点后执行的方法、适用的切点等。
    • <aop:pointcut>:定义切点,Spring只支持方法类型的切点,expression="execution(* 方法)"指明用作切点的方法。
    • <aop:before>:指明在切点前执行的方法,pointcut-ref属性指明适用的切点。
    • <aop:after>:指明在切点后执行的方法,无论切点是否成功执行都会执行,pointcut-ref属性指明适用的切点。
    • <aop:after-throwing>:在抛出异常后执行。
    • <aop:after-returning returning="返回值result">:在返回值之后执行,返回值名必须与方法形参名相同。
    • <aop:around>:紧贴代理对象方法前后执行,方法必须有返回值,可以修改目标方法的返回值。当使用环绕通知时,目标对象的方法只在环绕方法内部被调用后才可以执行,因为环绕通知底层采用MethodInterceptor,,而拦截器内部必须显式地调用后面的方法,进程才能推进。目标对象的方法可能有返回值,因此环绕通知必须有返回值。

    四 DAO

    1.什么是DAO?

    Data Access Object,数据访问对象,封装了一些对数据库进行持久化操作的方法,将持久化操作与一般的业务逻辑分开,便于维护与测试。

    2.数据源

    Spring提供的数据源DriverManagerDataSource,,在实际开发中很少用到,常用到第三方数据源C3P0、DBCP。

    DriverManagerDataSource:

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
           <property name="driverClassName">  <value>com.mysql.jdbc.Driver</value> </property>
           <property name="url"> <value>jdbc:mysql://localhost:3366/db_spring</value>  </property>
           <property name="username"> <value>root</value> </property>
           <property name="password"> <value>123</value> </property>
    </bean>

    C3P0:

    <bean id="c3p0"class="com.mchange.v2.c3p0.ComboPooledDataSource">
           <property name="driverClass" value="com.mysql.jdbc.Driver" />
           <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3366/db_spring"/>
           <property name="user" value="root" />
           <property name="password" value="123" />
    </bean>

    DBCP:

    <bean id="dbcp"class="org.apache.commons.dbcp2.BasicDataSource">
          <property name="driverClassName" value="com.mysql.jdbc.Driver" />
          <property name="url" value="jdbc:mysql://127.0.0.1:3366/db_spring"/>
          <property name="username" value="root" />
          <property name="password" value="123" />
    </bean>

    3.DAO类

    ⑴JdbcDaoSupport

    支持以基础的JDBC技术操作数据库的抽象类,开发者需要设置数据源,通过子类获得JdbcTemplate来访问数据库。利用框架提供的类DriverManagerDataSource创建与数据的连接,然后通过该类的实例获得Connection对象,后续操作同JDBC相同。Dao层实现继承JdbcDaoSupport,内部获取getJdbcTemplate进行底层数据库操作。

    Dao的实现类通过JdbcDaoSupport.getJdbcTemplate获取模板对象,通过模板对象封装的方法操作数据库:

    • update:在模板中增删改操作统一用updae方法。
    • queryForObject(slq,requiredClass,arg):用于查询一个字段,并且查询结果唯一。requeredClass表示查询字段的类型,以便对查询结果转型。
    • queryForList(slq,requiredClass,arg):用于查询一个字段,结果可能有多个。
    • queryForObject(sql,rowMapper,arg):查询结果是一个对象,其中rowMapper用于将查询字段封装成一个对象,查询结果必须包含对象的全部属性。
    • query(sql,rowMapper,arg):返回对个对象。
    • 数据源注入时自动创建模板,所以不需要在Dao的实现层显式注入JdbcTemplate的,即注入数据源时自动创建模板。
    • 系统自动在方法结束时销毁JdbcTemplate对象,因此每次在方法中使用时都需要重新创建。
    • HibernateDaoSupport:支持在Hibernate中操作数据库的抽象类,开发者需要设置SessionFactory,然后获得Hibernate的实现,HibernatDaoSupport底层实现复杂,效率低,不建议使用。

    4.继承

    JdbcDaoSupport/HibernateDaoSupport层级都高于对应的模板类,内部都提供了获取相应模板类的方法,与数库的交互通过模板类来完成。应用Spring提供的DAO模块时,自定义类通常继承XXXDaoSupport类,在自定义方法内部获得响应模板类来具体操作数据库。

    五 事务概述

    1.原理

    Spring事务管理是基于AOP实现的,而Spring的AOP是以方法为单位的,所以Spring的事务属性就是将事务应用到方法上的策略。

    2.事务管理器

    Spring提供了PlatformTransactionManager接口来管理事务,该类提供了用于事务管理的通知,可以将该类视作切面,两个重要的实现类:

    • DataSourceTransactionManager:适用于JDBC、Mybatis。
    • HibernateTransactionManager:适用于Hibernate。

    3.异常

    Spring在默认情况下,发生运行时异常回滚,编译时异常提交。程序员可以改变回滚方式。

    4.事务属性

    事务的四大属性分为传播行为、隔离级别、只读和超时。事务的传播行为用于确定是否将事务应用在方法上以及应用的策略,比如应用当前事务,新建事务。

    六 基于Spring AOP的事务管理

    1.四个要素

    代理工厂、目标对象、切点、切面。

    • 代理工厂:在SpringAOP事务管理中采用TransactionProxyFactoryBean充当代理工厂。
    • 切面:在Spring事务管理中PlatformTransactionManager充当切面。

    2.配置文件

    <bean id=""class="xxxTransactionProxyFactoryBean">//代理工厂
           <property name="target" ref=""/>//目标对象
           <property name="transactionManager"ref=""/>//切面
             //事务属性,就是事务应用到目标对象方法上的策略
           <property name="transactionAttributes>
                 <props>
                       <prop key="目标对象方法">事务四大属性</prop>
                 </props>
          </property>
    </bean>

    3.事务的属性

    因为目标对象中有多个方法,并不是所有方法都需要被事务管理,被事务管理的方法所需要的管理方式也不同,因此需要通过事务属性进行个性化定制,如ISOLATION_DEFAULT/PROPAGATION_REQUIRED/-Exception。

    4.异常

    Spring事务管理默认在发生编译时异常时提交,也可以设置成发生编译时异常回滚,在事务属性中设置:"-Excpetion",以负号开头,加异常,表示当发生该异常时事务回滚。

    七 基于AspectJ的事务管理

    1.配置文件的编写:

    <tx:advice id="advice"tansaction-manager="transactionManger">
             <tx:attributes>
                     <tx:method name="buyStock" isolation="DEFAULT"propagation="REQUIRED"rollback-for="StockProcessException" />
             </tx:attributes>
    </tx:advice>
    <aop:config>
             <aop:pointcut id="p01"expression="execution(xxxx)"/>
             <aop:advisor advice-ref="advice"pointcut-ref="p01"/>
    </aop:config>

    八 注解式开发

    以上两种事务管理是基于配置文件实现的,缺点是需要为每一个代理对象创建代理工厂,因此提供了基于注解的实现,可以方便地为多个对象创建代理:

    在配置文件中添加:

    <tx:annotation-driven transaction-manager="transactionManager"/>

    在目标对象方法上添加以下注解,设定事务的属性:

    @Transactional(isolation =Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor=StockProcessException.class)
  • 相关阅读:
    asp.net源码坊2015-3月第二周TOP10下载排行
    Asp.Net编程需要学习什么
    面试的同学看过来
    Asp.Net模板生成HTML页面
    毕业设计之房产中介系统源码
    HTML常用状态代码
    Asp.Net毕业设计论文
    网页常用Javascript
    intellij idea使用笔记
    bootstrap-table使用笔记
  • 原文地址:https://www.cnblogs.com/tonghun/p/6914594.html
Copyright © 2011-2022 走看看