Spring(1)

来源:互联网 发布:校园网络舆情监管制度 编辑:程序博客网 时间:2024/06/13 10:04

Spring(1)


Spring框架学习

Spring框架概述

之前学习了struts2、Hibernate两大框架,知道了:
struts2是基于MVC模式的表现层框架,主要是作为控制层组件,还可影响Javabean、JSP。
Hibernate是基于ORM规则的持久层框架,简化了JDBC操作,使得用户可以采用面向对象的思想操作数据库数据。

下面来到Spring,Spring是什么呢(WHAT)?为什么要使用Spring(WHY)?具体要怎么操作呢(HOW)?
Spring提供了一个全面的、一站式的JavaEE解决方案,主要包括以下功能:
- 基于依赖注入(控制反转IoC)的核心机制
- 声明式的面向切面编程(AOP)支持
- 与多种技术整合
- 优秀的Web MVC框架

Spring是企业应用开发的一站式选择,贯穿了表达层、业务层、持久层,而且并不会取代原有的框架,而是以高度的可定制性与之无缝结合。

Spring具有以下优点:
1. 低侵入式的设计,无代码污染。
2. 独立与各种应用服务器。
3. IoC容器降低了业务对象替换的复杂性,降低了组件之间的耦合度。
4. AOP容器允许将一些通用任务如安全、事务、日志等进行集中式处理。
5. Spring中的ORM和Dao支持提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问。
6. Spring的高度开放,并不会强制要求开发者完全依赖于Spring,可自由选择使用部分功能。

Spring分为六个模块,常用的有5个。
- Core
- AOP
- DAO(Jdbc、包含事务)
- ORM
- Web

环境搭建

1) 引入jar文件 (3.2版本) 【spring-core】

commons-logging-1.1.3.jar 【单独下载】
spring-beans-3.2.5.RELEASE.jar 【spring源码, bean节点管理】
spring-context-3.2.5.RELEASE.jar 【spring上下文类】
spring-core-3.2.5.RELEASE.jar 【IOC容器】
spring-expression-3.2.5.RELEASE.jar 【spring表达式】

注意:
使用的版本Spring3.2
在这个版本中,只有spring自身的核心功能,spring依赖的其他组件,需要单独下载。 例如:日志jar文件,就需要单独下载。
3.0版本之前包含组件自身和依赖的组件包、
3.0版本之后,依赖的组件包需要单独下载。

2) 新建applicationContext.xml , 源码中拷贝约束

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"    xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd"></beans>        

3) 配置

<!-- 创建Dao实例 --><bean id="userDao" class="cn.ustb.dao.UserDao"></bean><!-- 创建Service实例 --><bean id="userService" class="cn.ustb.service.UserService">    <property name="userDao" ref="userDao"></property></bean><!-- 创建Action实例 --><bean id="userAction" class="cn.ustb.action.UserAction">    <property name="userService" ref="userService"></property></bean>

4) 测试

  1. 创建容器对象(加载applicationContext.xml配置文件)
    new ClassPathXMLApplication("applicationContext.xml");
  2. 获取对象
    getBean("name or id");
// 从IOC容器获取对象@Testpublic void testApp2() throws Exception {    // 容器对象(加载applicationContext.xml配置文件)    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");    // 获取对象    UserAction userAction = (UserAction) ac.getBean("userAction");    userAction.execute();}

配置详解

<!-- 把对象加入IOC容器 --><!-- 细节1:    id 与   name:        id 不能以数字开头,不能含有特殊符号, 不能有空格、逗号等;  id 不能重复!        name 可以以数字开头,可以有特殊符合,如果name值重复,编译没有问题但运行报错!<bean id="user" name="user2,user3 user4" class="cn.ustb.a_config.User"></bean><bean name="user5" class="cn.ustb.a_config.User"></bean><bean id="user6" class="cn.ustb.a_config.User"></bean><bean id="user6" class="cn.ustb.a_config.User"></bean>--><!-- 细节2: (单例/多例)  --><!--     scope="singleton"   默认表示单例!           prototype    多例    init-method=""      在创建完对象之后执行初始化方法    destroy-method=""   在调用容器类的destroy()方法时候,对单例的对象有效!    lazy-init="true"    延迟初始化 / 这个属性的设置只对单例有影响,对多例没有任何影响!                        单例的对象默认是在创建容器的时候就创建所有单例的对象,如果希望在第一次访问的时候创建单例的对象,就设置延迟初始化    Bean生命周期:       bean在xml中配置,          singleton  单例            1) 创建对象                 如果有配置延迟初始化,                    lazy-init=true  如果单例的对象有配置延迟初始化, 在创建容器之后,在第一次从容器获取对象的时候                                 创建单例的对象!                如果没有配置或延迟初始化为默认值, 单例的对象会在创建容器的时候创建对象            2) 执行初始化方法 , init-method配置的方法会执行            3) 调用容器destroy() 方法时候,容器在销毁单例对象的实例的时候,会调用destroy-method对应的方法               此时bean对象会被销毁!          prototype  多例             1) 每次在从容器获取对象的时候,都会创建新的对象             2) 每次创建完对象后,就执行初始化方法             3) java会回收不用资源(jvm gc)      --><bean id="user"     class="cn.ustb.a_config.User"     init-method="init"     destroy-method="destroy_"     lazy-init="false"     scope="prototype"></bean>

创建对象的几种方式

创建对象的几种方式:
1) 调用无参数构造器
2) 调用有参数构造器
3) 工厂方法
* 静态方法
<bean id=”’ class=”” factory-method=””/>
* 非静态方法
<bean id=”factory” class=”..”>
<bean id=”” factory-bean=” factory” factory-method=”实例方法” />

4) 反射

<!--IOC容器, 创建对象 --><!-- 1) 调用无参数构造器 <bean id="user1" class="cn.ustb.b_create_obj.User"></bean> --><!-- 2) 调用有参数构造器, 创建对象 --><!-- String str = new String("Jack"); --><bean id="str" class="java.lang.String">    <constructor-arg value="Jack"></constructor-arg></bean><!-- 创建user对象,且赋值 --><!--     value 当直接给属性值的时候使用value赋值    ref   当引用的是IOC容器中的对象的时候,使用ref     --><bean id="user" class="cn.ustb.b_create_obj.User">    <constructor-arg index="0" type="int" value="10000"></constructor-arg>    <constructor-arg index="1" type="String" ref="str"></constructor-arg></bean><!--    3) 工厂创建对象        * 静态方法        * 非静态方法 --> <!-- * 工厂静态方法,创建对象 --> <!--       class 指定工厂的类型;        factory-method: 工厂类的静态方法  --> <bean id="user1" class="cn.ustb.b_create_obj.UserFactory" factory-method="getStaticInstace"></bean> <!-- * 非静态方法创建对象 --> <!-- 先创建工厂实例 --> <bean id="factory" class="cn.ustb.b_create_obj.UserFactory"></bean> <bean id="user" factory-bean="factory" factory-method="getInstace"></bean>

依赖注入(配置方式)

给对象属性赋值(Dependency Injection, 依赖注入),几种方式:

1) 构造函数赋值

<bean id="user1" class="cn.ustb.a_ioc.User" scope="prototype">    <constructor-arg index="0" value="jake"></constructor-arg>    <constructor-arg index="1" value="21221"></constructor-arg></bean>

2) set 方法注入值

普通字段赋值
+
集合属性 (list/map/property)

<!--IOC容器, 给对象属性赋值 --><bean id="user" class="cn.ustb.c_di.User">    <property name="id" value="1000"></property>    <property name="name" value="Jacky"></property>    <!-- list 集合赋值 -->    <property name="list">        <list>            <value>cn</value>            <value>usa</value>        </list>    </property>    <!-- map 集合赋值 -->    <property name="map">        <map>            <entry key="cn" value="China"></entry>            <entry key="usa" value="1234"></entry>        </map>    </property>    <!-- Properties 对象赋值 -->    <property name="prop">        <props>            <prop key="cn">China</prop>            <prop key="usa">America</prop>        </props>    </property></bean>

3) 案例

Dao/service/action实例,处理依赖关系
1、常用的通过set方法注入
+
2、内部bean
+
3、p 名称空间增加约束:xmlns:p="http://www.springframework.org/schema/p"

<!-- 配置: 需要创建的对象、对象依赖关系处理 --><!-- 方式1:通过set方法注入,这种方式最常用!  --><bean id="userdao" class="cn.ustb.d_di2.UserDao"></bean><bean id="userService" class="cn.ustb.d_di2.UserService">    <property name="userDao" ref="userdao"></property></bean><bean id="userAction" class="cn.ustb.d_di2.UserAction" scope="prototype">    <property name="userService" ref="userService"></property></bean><!-- 方式2: 内部bean --><!-- 总结: 当创建的对象,不被容器其他地方引用的时候,可以这样写! 这样写不通用,内部对象只能用一次 --><!-- 这里,action如果是单例,内部bean默认就是单例;  action如果是多例,内部bean就是多例 --><bean id="userAction2" class="cn.ustb.d_di2.UserAction" scope="prototype">    <property name="userService">        <bean class="cn.ustb.d_di2.UserService">            <property name="userDao">                <bean class="cn.ustb.d_di2.UserDao"></bean>            </property>        </bean>    </property></bean><!-- 方式3: p名称空间,给属性注入值      需要增加约束:xmlns:p="http://www.springframework.org/schema/p"--><bean id="userDao" class="cn.ustb.d_di2.UserDao"></bean><bean id="userService" class="cn.ustb.d_di2.UserService" p:userDao-ref="userDao"></bean><bean id="userAction" class="cn.ustb.d_di2.UserAction" p:userService-ref="userService"></bean>

自动装配

<!-- 方式4:自动装配 (了解) --><!--     a. default-autowire="byType"  配置到全局        当前所有的bean都采用”根据类型自动装配“    b. 配置到bean节点        autowire="byName"  根据名称自动装配, 会去容器找指定名称的对象,注入到set方法的参数中!        autowire="byType"  根据类型自动装配, 要确保改类型对应的对象在IOC容器中唯一,否则报错!    总结:        简化配置,但是维护麻烦! --><bean id="userDao" class="cn.ustb.e_autowire.UserDao" autowire="default"></bean><bean id="userService" class="cn.ustb.e_autowire.UserService"></bean><bean id="userAction" class="cn.ustb.e_autowire.UserAction"></bean>

依赖注入(注解方式)

注解汇总:

Class注解:
@Component 表示一个组件(类),把当前组件加入ioc容器,加入容器的组件的名称默认是类名第一个字母小写
@Component(“”) 指定加入ioc容器的组件类的类名

@Repository 标识是一个持久层的组件【DAO
@Service 标识是一个业务逻辑层的组件【Service
@Controller 标识是一个控制层的组件【Action

@Scope(“prototype”) 指定对象单例/多例【注解Class】

字段注解:
@Resource
1. 现根据字段名称(先id 再 name)查找。
2. 其次根据类型(Class)查找,如果该类型在ioc容器中有多个对象,报错。
3. 根据类型也没有找到对象,报错。

@Resource(name =“”) 会根据指定的名称去容器找对象自动注入

需要注意的一点细节:

  • Component+Resource足够了,只不过为了详细区分,将Component分出了持久层Repository、逻辑层Service、控制层Controller
  • Action因为是多例的,需要在Class上方注解@Scope(“prototype”)
  • Resource需要注解在setter的上方。
  • 最最最重要的,需要在bean.xml中配置开启注解扫描,即
    <context:component-scan base-package="cn.ustb.b_anno"></context:component-scan>
  • Resource无参的注解,现根据字段名查找,再根据类查找。

注解的示例

bean.xml:

<context:component-scan base-package="cn.ustb.b_anno"></context:component-scan>

Java:

@Component//可以带参@Component(name="userAction"),无参则默认类名首字母小写为组件名@Scope("prototype")//声明多例,默认单例public class UserAction {    private UserService userService;    public UserService getUserService() {        return userService;    }    /*     * Resurce要注解在setter方法之上     */    //@Resource(name="userService") //带参版    @Resource //先根据userService的字段名在容器中查找,再根据class类型查找(若同一类型存在多个实例抛出异常),再找不到也抛出异常    public void setUserService(UserService userService) {        this.userService = userService;    }    public void save(){        System.out.println("userAction save");        userService.save();    }}

配置方式和注解方式的对比:

配置:便于维护,但是配置较多较繁琐。
注解:开发方便,几个字母就能搞定,简化配置。但是不利于后期维护,若修改对象创建关系需要修改源代码。


Spring与Struts2的整合

Spring与Struts2整合的关键点:将Action的创建交给Spring的IOC容器。因此需要引入Spring-Web的包。

struts2-spring-plugin-2.3.4.1.jar 【struts源码】 添加了struts2对spring的支持
spring-web-3.2.5.RELEASE.jar 【spring源码】添加了spring对struts的支持

整合的完整步骤:

1、引入jar包

  • Struts核心jar
  • Spring
    • Core 核心 (5个)
    • Web 对web支持 (2个)

2、配置文件

  • bean.xml 【spring的配置文件,基本没什么变化。】
  • struts.xml【struts的配置文件,Class不需要写全类名,和bean的id保持一致,action实例可以从ioc容器获取。】
  • web.xml【配置spring的核心过滤器(监听器),启动时创建IOC容器】
    • struts2核心过滤器
    • spring配置文件读取
    • spring监听器,启动时候,配置加载springIOC容器

web.xml配置:

<!-- 配置struts核心过滤器 --><filter>    <filter-name>struts2</filter-name>    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping>    <filter-name>struts2</filter-name>    <url-pattern>/*</url-pattern></filter-mapping><!-- 配合SPring的核心过滤器,在启动服务器时加载spring配置,创建ioc容器 --><!-- 配置文件的位置 --><context-param>    <param-name>contextConfigLocation</param-name>    <param-value>classpath:bean-USER.xml</param-value></context-param><!-- 配置启动监听器,该类在spring-web包中 --><listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

将action的创建交给IOC容器。因此struts.xml中的class属性值为对应action在IOC中的id,而不再是类名。

需要注意的是,如果用到了注解,需要在bean.xml开启注解扫描

3、编写POJO、Action类。

需要再次强调的是,如果需要用到属性注入,在Action中的对象必须要new一下,除非在Spring中已经生成了该bean。

整合中出现过的问题:

1、action中的model注入部分为null

解决:model的不仅要设置setter方法,还要设置getter。并且要在Action中new一下。

2、action实例不了的原因,出现了nullpointer

原因:用到了注解,却忘记了在bean.xml中添加注解扫描。

原创粉丝点击