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的支持

。。。

 

  

  

原文地址:https://www.cnblogs.com/gucl/p/8138848.html