zoukankan      html  css  js  c++  java
  • Spring基础

    第一章 IOC

    一 、Spring 简介

      Spring是一个轻量级的开源的J2EE框架,为企业级应用提供了一站式的解决方案,解决了企业级应用开发的复杂性

      Spring是模块化的,总共有7个模块,可以选择使用需要的模块

      两大核心:IOCAOP

    二、控制反转(IOC)、依赖注入 (DI)、面向切面编程(AOP)

      在传统的开发中,当一个对象依赖另一个对象时,通常是在类中主动创建依赖对象,这样就增加了代码的耦合度,不利于代码的维护 

      控制反转的思想是 :对象不再自己主动创建依赖对象,而是把对象的创建和查找依赖对象的控制权交给了IOC容器

      依赖注入和控制反转是一回事,只是描述的角度不同,IOC侧重于原理,DI侧重于实现

    1. 对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的
    2. A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可

      AOP:在一个应用中,很多业务组件都需要关注一些功能,如事务管理、安全管理等,这些代码和业务组件的核心代码耦合在一起,不利于扩展和维护
      AOP的思想是把这些系统级的服务从业务核心代码中分离出来

    三、依赖注入

      一个Java文件或者一个类,就是一个bean,在这个类中有属性构造函数方法。如果一个类A依赖于类B,那么在A 中可以引入一个B类型属性b,然后为这个属性b生成get/set方法,或者在A的构造函数中传入B类型的参数初始化b,这样在bean配置文件中就可以通过配置在A需要用到b的时候注入到A中了

      Spring是通过反射的机制,调用set 构造方法实现了注入
      bean的配置中,各种标签属性:http://blog.csdn.net/everyong/article/details/46517461

    1. 依赖注入有三种形式:属性注入构造函数注入,工厂方法注入http://www.cnblogs.com/wkrbky/p/6369329.html
      • set注入
        <!--配置bean,配置后该类由spring管理--> 
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
        <!--(1)依赖注入,配置当前类中相应的属性--> 
        <property name="springDao" ref="springDao"></property> 
        </bean> 
        <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
        View Code
      • 构造注入
        <!--配置bean,配置后该类由spring管理--> 
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
        <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置--> 
        <constructor-arg ref="springDao"></constructor-arg> 
        <constructor-arg ref="user"></constructor-arg> 
        </bean> 
        <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean> 
        <bean name="user" class="com.bless.springdemo.vo.User"></bean>
        
        
        <!--参数不确定,比如同类型,使用index-->
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
        <constructor-arg index="0" ref="springDao"></constructor-arg> 
        <constructor-arg index="1" ref="user"></constructor-arg> 
        </bean>
        
        
        <!--不同类型是可以指定type-->
        <constructor-arg type="java.lang.String" ref=""/>
        View Code
      • 静态工厂的方法注入

        <!--配置bean,配置后该类由spring管理--> 
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction" > 
        <property name="staticFactoryDao" ref="staticFactoryDao"></property> 
        </property> 
        </bean> 
        <!--staticFactoryDao是从工厂类中的静态方法获得的--> 
        <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
        View Code
      • 实例工厂的方法注入

        <!--配置bean,配置后该类由spring管理--> 
        <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
        <property name="factoryDao" ref="factoryDao"></property> 
        </bean> 
        
        <!--对象factoryDao是从工厂类daoFactory调用方法返回的--> 
        <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean> 
        <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
        View Code
      • 注入值说明:
        • 注入字面值  如基本数据类型及其包装类还有String类的  可直接采用字面值方式注入,即用<value>  注意特殊字<    >     &     ''      '' '' 
        • 注入null值  使用<null/>标签表示null
        • 注入List、Map、Property
          <!--设置List值-->
          <bean id="person" class="com.xxx.Person">
              <property name="flist">
                  <list>
                      <value>篮球</value>
                      <value>音乐</value>
                      <value>旅行</value>
                  </list>
              </property>
          </bean>
          <!--集合合并tom是person的子类,merge设为false,那么tom就没有篮球,音乐,旅行-->
          <bean id="tom"parent="person">
              <property name="flist">
                  <list merge="true">
                      <value>看书</value>
                      <value>画画</value>
                  </list>
              </property>
          </bean>
          
          
          <!--设置map值-->
          <bean id="person" class="com.xxx.Person">
              <property name="fmap">
                  <map>
                      <entry>
                          <key>
                              <value>key1</value>
                          </key>
                          <value>唱歌</value>
                      </entry>
                      <entry>
                          <key>
                              <value>key2</value>
                          </key>
                          <value>跳舞</value>
                      </entry>
                      <entry>
                          <key>
                              <ref bean="keyBean" /><!-- 对象类型 -->
                          </key>
                          <ref bean="valueBean" />
                      </entry>
                  </map>
              </property>
          </bean>
          
          
          <!--配置java.Util.Properties类型的数据键和值都只能是字符串,没有value标签-->
          <bean id="person" class="com.xxx.Person">
              <property name="fmap">
                  <props>
                      <prop key="p1">唱歌</prop>
                      <prop key="p2">跳舞</prop>
                      <prop key="p3">读书</prop>
                  </props>
              </property>
          </bean>
          View Code
    1. bean的自动装配问题
      自动装配功能 就不需要ref进行手工装配bean ,可以减少配置文件的代码量,但不推荐使用,容易混乱
    2. bean配置的格式问题

    <!--1、属性(set设值)注入-->
    <!--需要Car类中有brand的set()方法-->
    <bean id="car" class="com.gcl.sprint02.Car">
        <property name="barnd">
            <value>奔驰</value>
        </property>
    </bean>
    
    
    
    <!--2、构造函数注入,需要Car类中提供构造方法,参数的顺序与constructor-arg出现的顺序无关(跟web.xml的顺序相关不同)-->
    <!--通过类型匹配入参-->
    <bean id="car" class="com.gcl.sprint02.Car">
        <constructor-arg type="String">
            <value>奔驰</value>
        </constructor-arg>
        <constructor-arg type="Double">
            <value>20000</value>
        </constructor-arg>
    </bean>
    
    <!--通过index匹配入参-->
    <bean id="car" class="com.gcl.sprint02.Car">
        <constructor-arg index="0"value="奔驰" ></constructor-arg>
        <constructor-arg index="1"value="德国" ></constructor-arg>
        <constructor-arg index="2"value="2000" ></constructor-arg>
    </bean>
    
    <!--构造函数重载,通过index和type匹配入参-->
    <bean id="car" class="com.gcl.sprint02.Car">
        <constructor-arg index="0"type="String"tvalue="奔驰" ></constructor-arg>
        <constructor-arg index="1"type="String"value="德国" ></constructor-arg>
        <constructor-arg index="2"type="int"value="20" ></constructor-arg>
    </bean>
    
    <!--3,非静态工厂方法注入,需要定义工厂类bean-->
    <!--car这个实例是通过CarFactory的creatCar()方法获得的-->
    <bean id="carFactory"calss="com.xxx.CarFactory"></bean>
    <bean id="car"factory-bean="carFactory"factory-method="creatCar"></bean>
    
    
    <!--4,静态工厂方法注入,不需要指向工厂类bean了,直接class指向CarFactory调用静态方法就行-->
    <bean id="car" class="com.xxx.CarFactory"factory-method="creatCar"></bean>
    总结

    四、Spring开发包

      首先下载springframework开发包:https://repo.spring.io/release/org/springframework/spring/
      把需要的jar包加入到工程中,另外还需要一个Commons-logging的jar包
      

      org.springframework.core.io.FileSystemResource;
      org.springframework.core.io.Resource;

      org.springframework.beans.factory.BeanFactory;
      org.springframework.beans.factory.xml.XmlBeanFactory;

    五、实例化IOC容器

    • 获取配置文件——>实例化IOC容器——>获得一个bean实例

        Spring实现IOC容器的方式有两种

      1. BeanFactory
        spring框架的基础设施,面向spring本身
      2. ApplicationContext
        BeanFactory的子接口,面向开发者,几乎所有的场合都可以使用ApprlicationContext而非底层的BeanFactory
        两个实现类:
        1,ClassPatnXmlApplicationContext:从类路径下加载配置文件
        2,FileSystemXmlApplicationContext:从文件系统下加载配置文件
    //1 读取配置文件
            Resource res = new FileSystemResource("SpringLearn.xml");
            
            //2 加载配置文件,启动IOC容器
            BeanFactory f = new XmlBeanFactory(res);
            
            //从IOC容器中获取一个person对象
            Person p =(Person) f.getBean("person");
    View Code



     第二章、AOP

    一、AOP简介

    1. 什么是AOP
      • AOP:Aspect Oriented Programming 面向切面编程,通过预编译运行期动态代理实现程序功能的统一维护的一种技术
      • 主要功能是:日志记录性能统计安全控制事务处理异常处理
    2. AOP的实现方式
      1. 预编译 如AspectJ
      2. 运行期动态代理(JDK的动态代理、CGLib的动态代理)
        如SpringAOP、JbossAOP
    3. 相关概念


      Advice的类型
    4. 有接口和无接口的SpringAOP实现区别
      1. Spring AOP默认使用标准的JavaSE的动态代理作为AOP代理,这使得任何接口或接口集都可以被代理
      2. Spring AOP也可以使用CGLib代理(如果一个业务对象并没有实现任何接口,只有一个实现类)
    5.  切面配置
      Spring所有的切面和通知器都必须包含在<aop:config>内(可以包含多个<aop:config>元素),然后可以配置aspect、pointcut、advice、Introductions、advisors等

      切入点的expression:




      引入(Introductions):允许一个切面声明一个实现一个指定接口(IterfaceA)的通知对象,并提供一个该接口的实现类来代表这些对象;由<aop:declare-parents>元素申明匹配到的类型拥有一个新的父类对象

      <bean id="theAspect"class="com.xxx.TheAspect"></bean>
      <bean id="abean"class="com.xxx.Abean"></bean>
      
      <!-- 首先定义一个切面类myAspect,然后定义切入点,例如 Abean类下的所有方法,然后配置通知,
      前置通知 在切入点执行之前执行beforeM方法,这个方法在切面类TheAspect里面还有切入点terurn后、抛出异常后、执行后、、、
      环绕通知:通知方法aroundM()的第一个参数必须是ProceedingJoinPoint类型的,例如pjp,在通知方法
      aroundM()中,pjp.proceed();表示切入点方法的执行,在这行代码的前后可以写在业务逻辑代码前后需要做的事情-->
      <aop:config>
          <aop:aspect id="myAspect" ref="theAspect">
              <aop:pointcut id="myPointcut" expression="execution(*com.xxx.Abean.*(..))"/>
              <aop:before method="beforeM"pointcut-ref="myPointcut"/>
              <aop:after-returning method="afterreturnM"pointcut-ref="myPointcut"/>
              <aop:after-throwing method="afterthrowingM"pointcut-ref="myPointcut"/>
              <aop:after method="afterM"pointcut-ref="myPointcut"/>
              <aop:around method="aroundM"pointcut-ref="myPointcut"/>
              <aop:around method="aroundMM"pointcut="execution(...........)"/>
              
              <!-- 匹配com.xxx.abc包下所有类的方法,这些类都有同一个父类InterfaceAimpl,而InterfaceAimpl类
              实现了InterfaceA接口,所以匹配到的类都拥有InterfaceAimpl里面的所有方法,它们的类型也可以转换为InterfaceA类型 -->
              <aop:declare-parents types-matching="com.xxx.abc.*(+)" 
              implement-interface="com.xxx.xxxx.InterfaceA"
              default-impl="com.xxx.xxxx.InterfaceAimpl"/>
          </aop:aspect>
      </aop:config>
      aop配置总结

    二、Spring AOP的API

    1. 切入点Pointcut
      NameMatchMethodPointcut:根据方法名字进行匹配,有一个成员变量mappedNames,匹配的方法名集合
    2. 前置通知Before advice
    3. 抛出异常通知
      Throwsacvice接口
    4. 后置通知
    5. 环绕通知
    6. 引入通知

    7. ProxyFactoryBean
      • org.springframework.aop.framework.ProxyFactoryBean是Spring AOP创建代理的最基础核心的一个类
      • 这可以完全控制切入点和通知,以及他们的顺序
    8. ................

    三、Spring对AspectJ的支持

    。。。

     

      

      

  • 相关阅读:
    P2149 [SDOI2009]Elaxia的路线
    P1346 电车
    P3174 [HAOI2009]毛毛虫
    P3047 [USACO12FEB]附近的牛Nearby Cows
    P4053 [JSOI2007]建筑抢修
    P2607 [ZJOI2008]骑士
    [HNOI2006]马步距离
    [POI2014]Hotel
    [BZOJ3856]Monster
    [BZOJ2819]Nim
  • 原文地址:https://www.cnblogs.com/gucl/p/8138848.html
Copyright © 2011-2022 走看看