javaweb入门之spring framework(02)

2017-05-03  本文已影响29人  小Q逛逛

Spring Framework的基本认识

一. spring(春天)的简介

Spring Framework 是一个开源的Java/Java EE全功能栈(full-stack)的应用程序框架.最初由Rod Johnson和Juergen Hoeller等开发。Spring Framework提供了一个简易的开发方式,这种开发方式,将避
免那些可能致使底层代码变得繁杂混乱的大量的属性文件和帮助类,是一个轻量级的Java开发框架.
    spring为了解决企业应用开发的复杂性而创建的。框架的主要优势之一
    就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为
     J2EE 应用程序开发提供集成的框架。
    * Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以   从Spring中受益。
    * Spring的核心是控制反转(IoC)和面向切面(AOP)。
    
    * EE开发分成三层结构
        * WEB层(view)   -- Spring MVC
        * 业务层(service)   -- Bean管理:(IOC)
        * 持久层(dao)   -- Spring的JDBC模板.ORM模板用于整合其他的持久层框架

        
  Spring框架,可以解决对象创建以及对象之间依赖关系的一种框架。且可以和其他框架一起使用;Spring与Struts,  Spring与hibernate(起到整合(粘合)作用的一个框架)
  
Spring提供了一站式解决方案:
    1) Spring Core  spring的核心功能: IOC容器, 解决对象创建及依赖关系
    2) Spring Web  Spring对web模块的支持。
                        -→ 可以与struts整合,让struts的action创建交给spring
                        -→ spring mvc模式
    3) Spring DAO  Spring 对jdbc操作的支持  【JdbcTemplate模板工具类】
    4) Spring ORM  spring对orm的支持: 
                        → 既可以与hibernate整合,【session】
                        → 也可以使用spring的对hibernate操作的封装
    5)Spring AOP  切面编程
    6)SpringEE   spring 对javaEE其他模块的支持

1.1 spring的特点

    * 方便解耦,简化开发
        * Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理
    * AOP编程的支持
        * Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
    * 声明式事务的支持
        * 只需要通过配置就可以完成对事务的管理,而无需手动编程
    * 方便程序的测试
        * Spring对Junit4支持,可以通过注解方便的测试Spring程序
    * 方便集成各种优秀框架
        * Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持
    * 降低JavaEE API的使用难度
        * Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

二. spring两个重要概念:IOC容器和AOP概念的理解.

2.1 IOC容器:inverse of control,控制翻转,意思是将对象的创建权限反转给Spring!!我们代码中不再像原来那样使用new关键字创建对象

* 使用IOC可以解决的程序耦合性高的问题.

下面通过代码来理解IOC容器:

2.2 创建web工程,结构如下

01文件结构.png

每个类的关键代码:

接口就一个相同的简单方法

public void save();

实现类的代码:

UserDao.class

public class UserDao implements IUserDao{

   @Override
   public void save() {
       // TODO Auto-generated method stub
       System.out.println("保存用户成功");
   }
   

UserService.class

public class UserService implements IUserService{
   
   private IUserDao userDao;
   
   @Override
   public void save() {
       // TODO Auto-generated method stub
       /*
        * 不使用IOC容器的写法
        * /
       userDao = new UserDao();
       userDao.save();
       
   }

UserAction.class

public class UserAction implements IUserAction{

   private IUserService userService;
       
   @Override
   public void save() {
       // TODO Auto-generated method stub
       /*
        * 不使用IOC容器的写法
        * */
       userService = new UserService();
       userService.save();
   }
   
   
   public static void main(String[] args) {
       /*
        * 不使用IOC容器的写法
        * /
       IUserAction userAction = new UserAction();
       userAction.save();
   }
   
}   

运行工程,console打印输出:保存用户成功

这是传统的编码方式,每个类的成员变量到需要相应的new,创建出来,耦合性比较强.

2.2 使用IOC容器管理对象的创建.

2.2.1:在原来的工程上添加spring-core的六个jar包,并且在src目录下创建applicationContext.xml文件,jar包add to buil path;

02文件结构.png

主要类添加set方法:

UserDao.class


public class UserDao implements IUserDao{

   @Override
   public void save() {
       // TODO Auto-generated method stub
       System.out.println("保存用户成功");
   }
}

UserService.class

public class UserService implements IUserService{
   
   private IUserDao userDao;
   public void setUserDao(IUserDao userDao) {
       this.userDao = userDao;
   }

   @Override
   public void save() {
       // TODO Auto-generated method stub
       /*
        * 不使用IOC容器的写法
       userDao = new UserDao();
       userDao.save();
       */
       userDao.save();
   }

}

UserAction.class

public class UserAction implements IUserAction{

   private IUserService userService;
   public void setUserService(IUserService userService) {
       this.userService = userService;
   }
   
   @Override
   public void save() {
       // TODO Auto-generated method stub
       /*
        * 不使用IOC容器的写法
       userService = new UserService();
       userService.save();
       */
       
       userService.save();
   }
   
   public static void main(String[] args) {
       /*
        * 不使用IOC容器的写法
       IUserAction userAction = new UserAction();
       userAction.save();
       */
       
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
       IUserAction action = (UserAction)ac.getBean("userAction");
       action.save();
   }
}

在applicationContext.xml文件添加bean约束和节点

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
       
       
    <bean id="userDao" class="com.it.dao.UserDao"></bean>
    <bean id="userService" class="com.it.service.UserService">
       <property name="userDao" ref="userDao"></property>
    </bean>
    <bean id="userAction" class="com.it.action.UserAction" scope="prototype">
       <property name="userService" ref="userService"></property>
    </bean>
       
</beans>

运行工程,console打印输出:保存用户成功.

我们发现,只需要通过在XML文件中进行配置,对象的创建就交给了spring的IOC容器.我们的代码就不再需要new 关键字进行创建,直接getBean("id")进行获取;这就是IOC的基本体现.

引出了另外一个概念:

   控制反转: 解决对象创建的问题 【对象创建交给别人】
   依赖注入: 在创建完对象后, 对象的关系的处理就是依赖注入 【通过set方法依赖注入】

8.3 IOC容器获取的两种方式

8.3.1 创建User类

User.java

public class User {

    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    
    public User() {
        // TODO Auto-generated constructor stub
        super();
        this.id = 22;
        this.name = "Jack";
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.id +"->"+this.name;
    }

}

IOC容器获取方式一:

    @Test
    public void testIOC1() {
        //1.把对象的创建交给IOC容器
        //这种加载方式会采用懒加载,调用getBean的时候才创建
        ClassPathResource resource = new ClassPathResource("applicationContext.xml");
        
        //2.创建容器对象(Bean工厂),IOC容器=工厂类+applicationContext.xml
        BeanFactory factory = new XmlBeanFactory(resource);
        User user = (User) factory.getBean("user");
        System.out.println(user);
    }

方式二:

//2.直接得到IOC容器(方便,常用)
        @Test
        public void testIOC2() {
            ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
            User user = (User) ac.getBean("user");
            System.out.println(user);
        }

要记得在applicationContext.xml配置user的bean节点.

8.3.2 IOC容器创建对象:

                创建对象, 有几种方式:
                1) 调用无参数构造器
                2) 带参数构造器
                3) 工厂创建对象
                        工厂类,静态方法创建对象
                        工厂类,非静态方法创建对象

测试几种创建方式:

配置applicationContext.xml,添加bean节点


 <!--1. 默认无参数构造函数 -->
        <bean id="user" class="com.it.entity.User"></bean>
        
        <!-- 2.带参数构造器 -->
        <bean id="user2" class="com.it.entity.User">
            <constructor-arg index="0" value="33"></constructor-arg>
            <constructor-arg index="1" value="Rose" type="java.lang.String"></constructor-arg>
        </bean>
        
        <!-- 3.引用参数 -->
        
        <bean id="name" class="java.lang.String">
            <constructor-arg value="Roses"></constructor-arg>
        </bean>
        
        <bean id="user3" class="com.it.entity.User">
            <constructor-arg index="0" value="44"></constructor-arg>
            <constructor-arg index="1" ref="name"></constructor-arg>
        </bean>
        
        <!-- 4.工厂类创建对象 -->
        
        <!-- 先创建工程 -->
        <bean id="factory" class="com.it.dependency.ObjectFacctory"></bean>
        
        <!-- 4.1工厂类,实例方法 -->
        <!-- factory实例方法创建user对象 -->
        <bean id="user4" factory-bean="factory" factory-method="getInstance"></bean>
        
        <!-- 4.2工厂类静态方法 -->
        <bean id="user5" class="com.it.dependency.ObjectFacctory" factory-method="getStaticInstance"></bean>

创建对象工厂类ObjectFactory.java

package com.it.dependency;
import com.it.entity.*;

public class ObjectFacctory {

    //工厂类创建对象
    
    //实例方法创建对象
    private User getInstance(){
        return new User(100, "Jack");
        
    }
    
    //静态方法创建对象
    private static User getStaticInstance(){
        return new User(102, "Jack2");
        
    }
}

测试类App.java,关键代码

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        @Test
        public void testIOCCreateObject() {
            //调用默认参数构造器
            User user = (User) ac.getBean("user");
            System.out.println(user);
        }
        
        @Test
        public void testIOCCreateObject1() {
            
            //带参数构造器
            User user = (User) ac.getBean("user2");
            System.out.println(user);
        }
        
        @Test
        public void testIOCCreateObject2() {
            
            //调用引用参数
            User user = (User) ac.getBean("user3");
            System.out.println(user);
        }
        
        @Test
        public void testIOCCreateObject3() {
            //调用工厂类实例方法
            User user = (User) ac.getBean("user4");
            System.out.println(user);
            
        }
        
        @Test
        public void testIOCCreateObject4() {
            //调用工厂类静态方法
            User user = (User) ac.getBean("user5");
            System.out.println(user);
            
        }

8.4 Spring框架的属性注入:对象依赖关系

对于类成员变量,常用的注入方式有两种
    * 构造函数注入
    * 属性setter方法注入(常用)
    * p名称空间
     * 自动装配(了解)
     * 注解(重点)

8.4.1构造函数注入

        <bean id="user2" class="com.it.entity.User">
            <constructor-arg index="0" value="33"></constructor-arg>
            <constructor-arg index="1" value="Rose" type="java.lang.String"></constructor-arg>
        </bean>

8.4.2 Set方法注入,需要注入的类要提供set方法

   <!-- set方法注入值 -->
     <bean id="userDao" class="com.it.dao.UserDao"></bean>
     <bean id="userService" class="com.it.service.UserService">
        <property name="userDao" ref="userDao"></property>
     </bean>
     
     <bean id="userAction" class="com.it.action.UserAction" scope="prototype">
        <property name="userService" ref="userService"></property>
     </bean>

8.4.3 内部bean

<!-- 内部bean赋值 -->
     <bean id="userAction" class="com.it.action.UserAction" scope="prototype">
        <property name="userService">
            <bean id="userService" class="com.it.service.UserService">
                <property name="userDao">
                    <bean class="com.it.dao.UserDao"></bean>
                </property>
            </bean>
        </property>
     </bean>

8.4.4 p命名空间

顶部的约束要添加,更改为

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    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">
        
     <!-- 
        给对象属性注入值:
            # p 名称空间给对象的属性注入值
             (spring3.0以上版本才支持)
     -->
     <bean id="userDao" class="com.it.dao.UserDao"></bean>
     
     <bean id="userService" class="com.it.service.UserService" p:userDao-ref="userDao"></bean>
     
     <bean id="userAction" class="com.it.action.UserAction" p:userService-ref="userService"></bean>
    
    
    <!-- 传统的注入: 
     <bean id="user" class="cn.it.entity.User" >
        <property name="name" value="xxx"></property>
     </bean>
    -->
    <!-- p名称空间优化后 -->
    <bean id="user6" class="com.it.entity.User" p:name="Jack0001"></bean>   
        
</beans>

8.4.5 自动装配

根据名称自动装配:autowire="byName"
自动去IOC容器中找与属性名同名的引用的对象,并自动注入;
• 根据类型自动装配:autowire="byType"
必须确保改类型在IOC容器中只有一个对象;否则报错。

    <bean id="userDao" class="com.it.dao.UserDao"></bean>   
    <bean id="userService" class="com.it.service.UserService" autowire="byName"></bean>
    <!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
    <bean id="userAction" class="com.it.action.UserAction" autowire="byName"></bean>

也可以定义到全局, 这样就不用每个bean节点都去写autowire=”byName”

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   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"><!-- default-autowire="byName">
       
       <bean id="userDao" class="com.it.dao.UserDao"></bean>   
       <bean id="userService" class="com.it.service.UserService"></bean>
       <!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
       <bean id="userAction" class="com.it.action.UserAction"></bean>

</beans>

8.4.6 注解方式

注解方式可以简化spring的IOC容器的配置!


使用注解步骤:
   1)先引入context名称空间
       xmlns:context="http://www.springframework.org/schema/context"
   2)开启注解扫描
       <context:component-scan base-package="cn.it"></context:component-scan>
   3)使用注解
       通过注解的方式,把对象加入ioc容器。

      创建对象以及处理对象依赖关系,相关的注解:
       @Component   指定把一个对象加入IOC容器

   @Repository   作用同@Component; 在持久层使用
   @Service      作用同@Component; 在业务逻辑层使用
   @Controller    作用同@Component; 在控制层使用 

   @Resource     属性注入
   
   属性注入的注解(说明:使用注解注入的方式,可以不用提供set方法)
   * 如果是注入的普通类型,可以使用value注解
       * @Value            -- 用于注入普通类型

   * 如果注入的是对象类型,使用如下注解
       * @Autowired        -- 默认按类型进行自动装配
           * 如果想按名称注入
           * @Qualifier    -- 强制使用名称注入

   * @Resource             -- 相当于@Autowired和@Qualifier一起使用
       * 强调:Java提供的注解
       * 属性使用name属性

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   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">
       
       
      <context:component-scan base-package="com.it"></context:component-scan>
       
</beans>

UserDao.java

package com.it.dao;

import org.springframework.stereotype.Component;

import com.it.interfaces.IUserDao;

@Component(value="userDao")
public class UserDao implements IUserDao{

   @Override
   public void save() {
       // TODO Auto-generated method stub
       System.out.println("保存用户成功");
   }
}

UserService.java


package com.it.service;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.it.dao.UserDao;
import com.it.interfaces.IUserDao;
import com.it.interfaces.IUserService;

@Component(value="userService")
public class UserService implements IUserService{
   
   @Resource
   private IUserDao userDao;

   @Override
   public void save() {
       userDao.save();
   }

}

UserAction.java


package com.it.action;

import javax.annotation.Resource;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

import com.it.interfaces.IUserAction;
import com.it.interfaces.IUserService;
import com.it.service.UserService;

@Component(value="userAction")
public class UserAction implements IUserAction{

   @Resource
   private IUserService userService;
   
   
   @Override
   public void save() {
       // TODO Auto-generated method stub
       userService.save();
   }
   
   
   public static void main(String[] args) {
       
       ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
       IUserAction action = (UserAction)ac.getBean("userAction");
       action.save();
   }

}

运行程序,控制台会输出: 保存用户成功

小结:

1) 使用注解,可以简化配置,且可以把对象加入IOC容器,及处理依赖关系(DI)

2) 注解可以和XML配置一起使用。

8.5 bean管理配置标签属性值

1. id属性和name属性的区别
    * id        -- Bean起个名字,在约束中采用ID的约束,唯一
        * 取值要求:必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号  id:不能出现特殊字符

    * name      -- Bean起个名字,没有采用ID的约束(了解)
        * 取值要求:name:出现特殊字符.如果<bean>没有id的话 , name可以当做id使用
        * Spring框架在整合Struts1的框架的时候,Struts1的框架的访问路径是以/开头的,例如:/bookAction

2. class属性          -- Bean对象的全路径
3. scope属性          -- scope属性代表Bean的作用范围
    * singleton         -- 单例(默认值)
    * prototype         -- 多例,在Spring框架整合Struts2框架的时候,Action类也需要交给Spring做管理,配置把Action类配置成多例!!
    * request           -- 应用在Web项目中,每次HTTP请求都会创建一个新的Bean
    * session           -- 应用在Web项目中,同一个HTTP Session 共享一个Bean
    * globalsession     -- 应用在Web项目中,多服务器间的session(集群)

4. Bean对象的创建和销毁的两个属性配置(了解)
    * 说明:Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法
    * init-method       -- 当bean被载入到容器的时候调用init-method属性指定的方法
    * destroy-method    -- 当bean从容器中删除的时候调用destroy-method属性指定的方法
        * 想查看destroy-method的效果,有如下条件
            * scope= singleton有效
            * web容器中会自动调用,但是main函数或测试用例需要手动调用(需要使用ClassPathXmlApplicationContext的close()方法)

8.7 集合的注入

1. 如果是数组或者List集合,注入配置文件的方式是一样的
    <bean id="collectionBean" class="com.it.CollectionBean">
        <property name="arrs">
            <list>
                <value>22</value>
                <value>44</value>
            </list>
        </property>
    </bean>

2. 如果是Set集合,注入的配置文件方式如下:
    <property name="sets">
        <set>
            <value>哈哈</value>
            <value>呵呵</value>
        </set>
    </property>

3. 如果是Map集合,注入的配置方式如下:
    <property name="map">
        <map>
            <entry key="小明" value="38"/>
            <entry key="小花" value="38"/>
            <entry key="如花" value="29"/>
        </map>
    </property>

4. 如果是properties属性文件的方式,注入的配置如下:
    <property name="pro">
        <props>
            <prop key="uname">root</prop>
            <prop key="pass">123</prop>
        </props>
    </property>

上一篇 下一篇

猜你喜欢

热点阅读