zoukankan      html  css  js  c++  java
  • spring 2.x总结

    Spring是分层的java SE/EE应用一站式的轻量级开源框架,以IOC和AOP为内核,提供了展示层spring mvc和持久层spring jdbc,以及业务层事务管理等众多的企业级应用技术。

    相关的网站:

    spring.jactiongroup.net

    www.springside.org.cn

    www.javaeye.com

    spring的体系结构

    spring共有1400个类,其框架按功能分为7个模块。



    spring核心模块:实现了IOC的功能,将类与类之间的依赖关系从代码中脱离出来,用配置的方式进行依赖描述,其中BeanFactory是核心接口。

    ApplicationContext模块:核心模块使得spring成为一个bean的容器。ApplicationContext构建在核心之上,扩展了BeanFactory,添加了i18n,Bean生命周期控制,框架事件体系,资源加载透明化,以及企业服务的支持如邮件、任务调度、jndi定位、ejb集成、远程访问等。

    AOP模块:Aop是横切逻辑编程的思想。spring提供了满足Aop Alliance规范的实现,还整合了AspectJ这种AOP语言级的框架。

    Spring DAO:Spring使用模板编程对原始的jdbc进行薄层的封装,简化了数据库操作,建立一套面向DAO层的异常体系,将各种检查型异常转为非检查型异常。提供了声明式的事务服务,将事务的管理从代码中剥离,仅专注于业务的实现。

    ORM模块:Spring通过ORM模块提供了整合多种ORM框架的能力。

    Spring Web模块:建立在ApplicationContext模块之上,提供各种Web应用的工具类,如通过Listener或Servlet初始化Spring容器,将Spring容器注册到web容器中,透明化文件上传,整合其他Web框架等。

    Spring MVC模块:Spring自己提供一个完整的类似于struts或web work的MVC框架。

    spring 2.0的新功能

    1、简化配置文件的编写
    1.x版本使用dtd格式,而2.x引入schema格式,提供了不同的名字空间,简化配置。

    2.新的bean的作用域
    1.x版本只支持单例singleton和原型prototype两个作用域,2.x提供三个依赖web环境的作用域,还允许通过钩子技术自定义bean的作用域。

    3.AOP的增强
    1.x中AO是xml格式来配置的。
    2.x中引入全新的AOP命名空间,通过AspectJ切点表达式完成切面定义。
    2.x开始支持通过@AspectJ注解定义切面,这样当对象是在容器外被创建时,会被静态织入,从而产生对容器的回调。进行领带关系的注入,而原来对容器外的对象,Spring是不能管理的。

    4.持久层增强
    2.x进行声明式事务配置更加简单,同时增强了JPA的支持。

    5.展示层的增强
    Spring MVC开始采用契约模式,意味着用户可以通过命名规范的约束来减少配置文件。

    6.其它
    开始动态脚本语言ruby groovy beanshell等。
    提供简单的JMS容器,支持JMX和JCA,表明态度,全面支持J2EE规范。
    通过TaskExecutor接口对JDK5.0新增的任务执行器进行封装,允许开发人员更灵活地开发和JDK版本无关的任务执行器。
    通过注解和泛型,对对象进行静态注入。

    何谓IOC?
    Inverse of Control字面意为控制反转,即某一个接口具体实现类的选择控制权从调用类中移除,转交给第三方裁决。

    Martin Fowler提出DI(Dependency Injection)的概念替代IOC,即调用类对接口实现类的依赖关系由第三方注入。

    IOC的方式
    工厂:代码中未完全消除依赖,而是发生了依赖转移。
    容器:完全从代码中消除依赖,Spring提供了setter/构造子/接口注入。

    BeanFactory和ApplicationContext的区别:
    Bean工厂是spring框架中最核心的接口,提供了高级IOC的配置机制,它是SPRING框架的基础而面向SPRING本身,称之为IOC容器。
    ApplicationContext构建在Bean工厂之上,提供更多面向应用的功能,面向程序员称之为Spring容器。

    WebApplicationContext
    专门为web应用准备的,它允许从相对WebRoot的路径中装配配置文件完成初始化,它扩展了ApplicationContext, WebApplicationContext定义了一个常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在服务器启动时,WebApplication实现就以此键存放在ServletContext中,Spring提供了一个工具类用于获取WebApplication实例。如下:
    WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)

    WebApplicationContext必须在web容器启动的前提下才能初始化,因此Spring提供了两个专用于启动WebApplicationContext的Servlet和监听器。
    org.springframework.web.context.ContextLoaderServlet
    org.springframework.web.context.ContextLoaderListener

    父子容器
    Spring的IOC容器可以建立父子层级关联的容器体系。
    子容器可以访问父容器中的bean,但父容器不能访问子容器中的bean,在容器内,bean的id必须唯一。但子容器可以拥有一个和父容器同id的bean.

    注入方式的考虑
    使用构造子注入的理由:
    保证属性在bean实例化时设置好。
    不需要为每个属性提供setter,更好地封装了类变量。
    反对理由:
    类的属性太多,构造函数的签名太复杂。
    可选的属性,必须注入null。
    有时会造成循环依赖。

    注入参数详解
    1、字面值
    可用字符串表示的值用<value>注入。
    如果字符串中包括5个特殊字符,可使用转义实体符号。
    < &lt;
    > &gt;
    & &amp;
    " &quot;
    ' &apos;
    或者使用<![CDATA[包括特殊字符的字符串]]>

    2、引用其它bean
    <ref>元素有以下三个属性引用容器中其他的bean。
    bean:引用同一个容器或父容器的bean.
    local:引用同一个配置文件中定义的bean.
    parent:引用父容器中的bean.
    父了容器的关系可在构造容器时指定。
    new ClasssPathXmlApplicationContext(new String[]{"配置文件",...},父容器引用);

    3、内部Bean
    如果一个bean只能被另一个bean使用,则可用内部bean的方法注入。
    <bean ...>
        <property name="属性名">
            <bean class="类名">
                <property ...>
            </bean>
        </property>
    </bean>
    内部bean没有名字,即使提供id,name,scope也会被忽略。scope默认为prototype.

    4、null值
    spring将<value></value>视为空字符串。
    空值为<null/>表示。

    5、级联属性
    <bean id="boss" class=".....Boss类">
        <property name="car.brand" value="benchi"/>
    </bean>

    public class Boss{
        private Car car=new Car();
        public Car getCar(){
            return car;
        }
        public void setCar(Car c){
            this.car=c;
        }
    }

    6、集合类型

    Object[]和List用<list>

    Set用<set>

    Map用

    <map>

        <entry>

            <key><ref .../></key>

            <value> ....</value>

        </entry>

    </map>

    properties用

    <props>

        <prop key="字符串">字符串</prop>

    </props>

    其中map的key和值可以使用任何类型,而props只能使用字符串。

    <bean>之间的关系:

    1.继承

    <bean id="parentBean" class="..." abstract="true"/>

    <bean id="subBean" parent="parentBean"/>

    其中abstract="true"表示不产生实例,后者继承前者的配置。注意不并等同于类的继承。

    2.依赖

    <ref>标签建立对其他bean的依赖关系,能保证实例化一个bean时,它所依赖的其他bean已初始化。

    3.引用

    <idref>

    Bean的作用域

    spring1.x的作用域有2个:singleton和prototype

    spring 2.x中针对WebApplicationContext添加了新的作用域,request/session/globalSession.

    1.x的版本采用singleton="true|false"

    2.x的版本兼容以上写法,但推荐使用scope="作用域"

    spring的默认作用域为singleton,在容器启动时会自动实例化所有的singleton的bean并缓存于容器之中。

    好处:提前实例化可发现一些潜在的问题并加快了运行效率。

    如果不希望提前实例化可以使用lazy-init="true"来控制,但如果该bean被其它bean所使用,则该设置会忽略。

    prototype指多例,在默认情况下,spring会在启动时不实例化prototype的bean,而且spriing容器将prototype的bean交给调用者后就不管它的生命周期。

    新增的3种作用域在使用之前要额外配置web.xml

    在低版的web容器(servlet2.3)之前,用过滤器

    org.springframework.web.filter.RequestContextFilter过滤所有的请求

    在高版的web容器中用请求监听器配置。

    org.springframework.web.context.request.RequestContextListener

    将web相关作用域的Bean注入到singleton或prototype的bean中,我们需要如下配置。

    1.声明aop的名字空间

    xmlns:aop="http://www.springframework.org/shema/aop"

    2.创建代理

    <bean name="a" class="..." scope="request">

        <aop:scoped-proxy/>

    </bean>

    3.引用web作用域的bean

    <bean id="b" class="...">

        <roperty name="..." ref="a"/>

    </bean>

    注入给b的a是动态生成的代理对象,增加了判断当前的b需要取得哪个请求相关的a。

    基于@AspectJ和schema的AOP

    在spring1.x中定义一个切面是比较麻烦的,需要实现专门的接口并进行一些较为复杂的配置。

    在spring2.x中AOP已经焕然一新,用户可以使用@AspectJ注解非常容易地定义一个切面,不需要实现任何接口,对于没有使用JDK5.0的项目,则可以通过基于schema的配置定义切面其方便程度与@AspectJ相差无几。

    着手使用@AspectJ

    使用@AspectJ之前,JDK的版本是5.0以上。

    需要spring/lib/asm的关联库(轻量级的字节码处理框架,因为java的反映已经无法获得入参名,用asm处理方法入参名)。

    需要spring/lib/aspectJ注解类库及相应的解析类库。

    用@AspectJ将一个POJO类定义为一个切面

    @AspectJ                                                    //标识切面

    public class ...{

        @Before ("execution (* greetTo(..))")    //定义切入点和增强类型

         public void ...(){

                   //具体的增强逻辑

        }

    }

    通过编程的方式使用@AspectJ切面

    AspectJProxyFactory f=new AspectJProxyFactory();

    f.setTarget(...);      //设定目标对象

    f.addAspect(....class);    //设定切面类

    ... proxy=f.getProxy();    //生成代理

    通过配置使用@AspectJ切面

    <bean id="target" class="..."/>   //定义目标对象

    <bean class="@AspectJ切面类"/>

    <bean class="org.springframework.aop.aspectj.annotaion.AnnotationAwareAspectJAutoProxyCreator"/>

    如果使用基于schema的aop命名空间就更简单了。

    将最后一句改为<aop:aspectj-autoproxy/>

    @AspectJ语法基础

    @AspectJ使用jdk5.0注解和正规的AspectJ5的切点表达式描述切面。

    切点表达式函数

    spring支持9个@AspectJ切点表达式函数

    大致分为以下4种类型:

    方法切点函数

    execution()

    方法匹配模式串

    @annotation()

    方法注解类名

    方法入参切点函数

    args()

    类名

    @args()

    类型注解类名

    目标类切点函数

    within()

    类名匹配串

    target()

    类名

    @within()

    类型注解类名

    @target()

    类型注解类名

    代理类切点函数

    this()

    类名

    函数入参中使用通配符

    @AspectJ支持3种通配符

    *匹配任意字符,但只能匹配一个元素。

    ..匹配任意字符,可以匹配多个元素,但在表示类时,必须和*联合使用,而在表示入参时可单独使用。

    +表示按类型匹配指定类的所有类,仅能跟在类名后面。

    @AspectJ函数按其是否支持通配符及支持程度可以分为3类。

    支持所有的通配符execution(),within()

    仅支持+通配符args(),this(),target()

    不支配通配符@args(),@within(),@target(),@annotation

    除了execution(),within()之外,其它函数除了可以指定类名外,也可以指定变量名,并将目标对象中的变量绑定到增强的方法中。

    逻辑运算符

    切点表达式由切点函数组成,切点函数之间还可以进行逻辑运算,组成切点。

    &&与操作,相当于切点的交集,在配置文件中使用时可以用and

    ||或操作,相当于切点的并集,or是等效的操作符

    !非操作,相当于切点的反集,not是等效的操作符

    在spriing中使用and ,or ,not时,允许不在前后添加空格,如果not位于表达式的开头,则必须在开头添加一个空格,否则将产生解析错误。

    不同的增强类型

    @AspectJ为各种增强类型提供了不同的注解类,位于org.aspectj.lang.annotation包中,它们的留存期都是RetentionPollicy.RUNTIME,标注目标都是METHOD.

    @Before

    前置增强,相当于BeforeAdvice

    @AfterReturning

    后置增强,相当于AfterReturningAdvice

    @Around

    环绕增强,相当于MethodInterceptor

    @AfterThrowing

    抛出增强,相当于ThrowsAdvice

    @After

    Final增强,不管是抛出异常或正常退出,该增强都会执行,该增强没有相应的接口,可以把它看作为ThrowsAdvice和AfterReturningAdvice的混合物。

    基于schema的配置切面

    如果项目没有使用JDK5.0,那么无法使用基于@AspectJ注解的切面,Spriing提供了基于schema配置的方法,完全可代替基于@AspectJ注解声明切面的方式。

    一个切面的配置例子

    <aop:config proxy-target-class="true">//true表示CGLIB,false表示jdk动态代理

        <aop:aspect ref="包含增强方法的bean">

            <aop:before pointcut="target(类名) and execution (* 方法名(..))" method="增强的方法"/>

        </aop:aspect>

    </aop:config>

    一个<aop:aspect>元素定义一个切面,其内部可以定义多个增强

    一个<aop:config>中可以定义多个切面

    一个<aop:before>声明一个前置增强,并通过pointcut属性定义切点表达式,切点表达式的语法与@Aspect中所用的语法完全相同

    前例中pointcut属性声明的切点是匿名的切点,它不能被其他增强或其他切面引用。

    配置命名切点

    <aop:pointcut id="切点名" expression="切点表达式"/>

    该标记可以放在<aop:aspect>中,则只能在一个切面中被访问。

    该标记可以放在<aop:aspect>外,则只能在所有切面中被访问。

    每一种增强类型元素都拥有pointcut,point-ref,method这3个属性。

  • 相关阅读:
    01_3_创建一个Action
    01_2_Namespace命名空间
    01_1_Socket实现
    03_2_JAVA中的面向对象与内存解析
    01_1_Struts环境搭建
    Zabbix通过Orabbix监控Oracle数据库
    Zabbix通过JMX方式监控java中间件
    nginx启用status状态页
    zabbix数据库分表的实现
    配置sudo记录日志
  • 原文地址:https://www.cnblogs.com/sunwei2012/p/1900178.html
Copyright © 2011-2022 走看看