SpringIOC

来源:互联网 发布:刷枪软件 永久免费 编辑:程序博客网 时间:2024/05/16 00:41

一、spring框架概念
spring是众多开源java项目中的一员,基于分层的javaEE应用一站式轻量级开源框架,主要核心是Ioc(控制反转/依赖注入) 与Aop(面向切面)两大技术,实现项目在开发过程中的轻松解耦,并极大的提高项目的开发效率。

在项目中引入spring立即可以带来下面的好处 降低组件之间的耦合度,实现软件各层之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。 容器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。

二、spring的七大模块
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。

1.核心容器Spring Core: 核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 思想将应用程序的配置和依赖性规范与实际的应用程序代码分开。

2.Spring 上下文Spring Context:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

3.Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,就可以将声明性事务管理集成到应用程序中。

4.Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

5.Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

6.Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

7.Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

三、Spring 框架环境搭建
环境要求:jdk 1.7 及以上、Spring版本:4.3.2
1.建立普通的java 工程
2)新建lib目录,并将一下5个核心jar包拷贝过来,并加入classpath中
spring-beans-4.3.2.RELEASE.jar、spring-context-4.3.2.RELEASE.jar、spring-core-4.3.2.RELEASE.jar、spring-expression-4.3.2.RELEASE.jar、commons-logging-1.2.jar
下载地址: http://repo.spring.io/libs-release-local/org/springframework/spring/4.3.2.RELEASE/
这里写图片描述

此时下载的jar包属于spring的jar,环境搭建需要依赖commons-logging-1.2.jar

3)spring 配置文件的编写
在src下新建xml文件,并拷贝官网文档提供的模板内容到xml中,配置bean到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"    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl"></bean></beans>

4)验证spring框架环境是否搭建成功
验证的方式通过junit4 进行验证
加载xml文件的方式有两种一般使用第一种
I.通过当前类路径的方式加载xml文件,启动spring容器框架
II.根据文件系统方式寻找配置文件,启动spring容器框架(不推荐)
这里写图片描述

思考:Bean 是如何被实例化的?—工厂模式(简单模拟实现工厂模式)
简单工厂模式:抽象产品角色,具体产品角色,工厂角色
Spring的核心容器实现了IOC, BeanFactory和ApplicationContext是了解Spring核心的关键。
  Spring中,两个最基本、最重要的包,org.springframework.beans和org.springframework.context。框架中代码中大量引用了Java中的反射机制,为Spring的反向控制特性提供了基础。
BeanFactory提供了一种配置机制来管理任何种类的Bean
ApplicationContext建立在BeanFactory之上,并增加了其他的功能,比如对国际化的支持、获取资源、事件传递等。
IOC 详情解析参考http://www.cnblogs.com/ITtangtang/p/3978349.html

四、模拟spring容器
思路:
1.读取spring 配置文件,并解析配置文件(dom4j方式解析)
2.根据读取的配置信息,利用利用反射技术完成bean的实例化过程
3.对外提供getbean方法,从容器中获取bean

/** * @author Administrator * 1.根据构造方法传入文件 * 2. 解析xml  使用dom4j * 3.实例化bean  * 4.对外提供getBean 方法 */public class SxtClassPathXmlAppcliation {    private List<SxtBean> beans=new ArrayList<SxtBean>();//保存每个元素bean    private Map<String, Object> map=new HashMap<String,Object>();//用来保存实例化的bean对象    public SxtClassPathXmlAppcliation(String fileName) {        this.readXml(fileName);// 读取并解析xml        this.instanceBeans();//实例化bean    }    /**     * 对外提供getbean 方法     * @param name     * @return     */    public Object getBean(String name){        return map.get(name);    }    private void instanceBeans() {        for(SxtBean sxtBean:beans){            try {                map.put(sxtBean.getId(), Class.forName(sxtBean.getClazz()).newInstance());            } catch (Exception e) {            }        }    }    private void readXml(String fileName) {        try {            SAXReader saxReader=new SAXReader();// 创建sax 解析对象            URL url=this.getClass().getClassLoader().getResource(fileName);            Document document=saxReader.read(url);// 从内存中读取文档            Map<String, String> map=new HashMap<String,String>();            map.put("sxt", "http://www.springframework.org/schema/beans");//添加命名空间            XPath xPath=document.createXPath("//sxt:bean");//设置查询路径            xPath.setNamespaceURIs(map);            List<Element> elements=xPath.selectNodes(document);                 for(Element element:elements){                SxtBean sxtBean=new SxtBean();                sxtBean.setId(element.attributeValue("id"));                sxtBean.setClazz(element.attributeValue("class"));                          beans.add(sxtBean);                     }               } catch (DocumentException e) {            e.printStackTrace();        }    }}Bean 定义

package com.shsxt.vo;

public class SxtBean {
private String id;

private String clazz;public String getId() {    return id;}public void setId(String id) {    this.id = id;}public String getClazz() {    return clazz;}public void setClazz(String clazz) {    this.clazz = clazz;}

}

理解:Spring 容器在启动的时候 读取xml配置信息,并对配置的 bean 进行实例化(这里模拟的比较简单,仅用于帮助大家理解),同时通过上下文对象提供的getbean方法拿到我们配置的bean对象,从而实现外部容器自动化维护并创建bean的效果。

五、Spring Ioc实例化bean对象的三种方式
1、构造器的方式实例化bean对象

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl"></bean>

2、静态工厂方法方式实例化bean
特点:
I.要有该工厂类及工厂方法
II.工厂方法为静态的

<bean id="sxtBeanFactory" class="com.shsxt.factory.SxtBeanFactory"     factory-method="getUserServiceBean"></bean>

3、实例化工厂方式创建bean
相比较静态工厂实现
I.工厂方法为非静态方法
II.需要配置工厂bean,并在业务bean中配置factory-bean,factory-method属性

<bean id="sxtBeanFactory" class="com.shsxt.factory.SxtBeanFactory"></bean><bean id="userServiceImpl"  factory-bean="sxtBeanFactory" factory-method="getUserServiceBean2"></bean>

spring三种实例化bean的方式比较
方式一:通过bean的缺省构造函数创建,当各个bean的业务逻辑相互比较独立的时候或者和外界关联较少的时候可以使用。

方式二:利用静态factory方法创建,可以统一管理各个bean的创建,如各个bean在创建之前需要相同的初始化处理,则可用这个factory方法险进行统一的处理等等。

方式三:利用实例化factory方法创建,即将factory方法也作为了业务bean来控制,
1可用于集成其他框架的bean创建管理方法,2能够使bean和factory的角色互换。
开发中项目一般使用一种方式实例化bean,采用第一种方式最好,交给spring托管,使用时直接拿来使用即可。

六、Spring 依赖注入(Dependency Injection 即DI)
1、手动与引入的问题
这里写图片描述
图1
这里写图片描述
图2
对比发现:图二中对于UserServiceImpl02 对象的创建并没有像图一那样主动的去实例化,而是通过set方法形式将AccountServiceImpl传入过来,从而实UserServiceImpl02 对UserDao类的依赖。
而实际创建对象的幕后对象即是交给了外部来创建。

2.Spring Ioc 注入
Spring 支持的注入方式有set 注入与构造器注入
2.1.Set注入
xml配置(同时 spring 也提供了对于基本数据类型的set注入方式)

<?xml version="1.0" encoding="UTF-8"?><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="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">        <property name="userDao" ref="userDao"></property>    </bean>       <bean id="userDao" class="com.shsxt.dao.UserDao"></bean></beans>

Java 类

package com.shsxt.service.impl;import com.shsxt.dao.UserDao;import com.shsxt.vo.User;public class UserServiceImpl {    private UserDao userDao;    public void setUserDao(UserDao userDao) {        this.userDao = userDao;    }    public UserDao getUserDao() {        return userDao;    }    public void saveUser(User user){        System.out.println("userName:"+userName+"price:"+price);        userDao.add(user);    }}

基本数据类型 set 注入 提示

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">        <property name="userDao" ref="userDao"></property>       <property name="userName" value="sxt">        </property>        <property name="price" value="123">        </property></bean>同时对应Service 提供对应属性字段 以及getset方法即可

2.2构造器注入
xml配置(也提供对于基本数据类型的构造器注入值得方式)

<bean id="userDao" class="com.shsxt.dao.UserDao"></bean>                  <bean id="userServiceImpl2" class="com.shsxt.service.impl.UserServiceImpl2">            <constructor-arg ref="userDao"></constructor-arg>       </bean>

Java 类 提供构造函数

package com.shsxt.service.impl;import com.shsxt.dao.UserDao;import com.shsxt.vo.User;public class UserServiceImpl2 {    private UserDao userDao;    public UserServiceImpl2(UserDao userDao) {        this.userDao = userDao;    }    public void saveUser(User user){        userDao.add(user);       }}

构造器注入基本数据类型提示
Index属性为参数顺序 如果只有一个参数 index 可以不设置。

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">        <constructor-arg name="userName" index="0" value="123">        </constructor-arg>        <constructor-arg name="userPwd" index="1" value="321"></constructor-arg>    </bean>

2.3静态工厂注入

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">        <property name="userDao" ref="sxtBeanFactory"></property></bean><bean id="sxtBeanFactory" class="com.shsxt.factory.SxtBeanFactory" factory-method="getBean"></bean>

静态工厂类

package com.shsxt.factory;import com.shsxt.dao.UserDao;import com.shsxt.dao.impl.UserDaoImpl;public class SxtBeanFactory {    public static UserDao getBean(){        return new UserDaoImpl();       }}

UserserviceImpl 提供 属性与UserDao 与set 方法
2.5 实例化工厂

<bean id="sxtBeanFactory" class="com.shsxt.factory.SxtBeanFactory" ></bean><bean id="userDaoDynamicFactory" factory-method="getBean2" factory-bean="sxtBeanFactory" ></bean><bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl" >    <property name="userDao" ref="userDaoDynamicFactory"></property> </bean>

重点掌握set注入,其他三种了解即可。实际开发中基本使用set方式注入bean。
3.循环依赖的问题的产生
Bean通过构造器注入,之间彼此相互依赖对方导致bean无法实例化。

使用构造注入可以在构建对象的同时一并完成依赖关系的建立,对象一建立则所有的一切也就准备好了,但如果要建立的对象关系很多,使用构造注入会在构建函数上留下一长串的参数,且不易记忆,这时使用Set注入会是个不错的选择。

  使用Set注入可以有明确的名称,可以了解注入的对象会是什么,像setXXX()这样的名称会比记忆Constructor上某个参数的位置代表某个对象更好。

4.Ioc集合类型属性注入(了解)
4.1.list集合注入

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">    <property name="list">        <list>            <value>1</value>            <value>2</value>            <value>3</value>            <value>4</value>        </list>    </property></bean>

4.2.set集合注入

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">    <property name="set">        <set>            <value>1</value>            <value>2</value>            <value>3</value>            <value>4</value>            <value>5</value>        </set>    </property></bean>

4.3.map 类型属性注入

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">    <property name="map">        <map>            <entry>                <key>                    <value>1</value>                </key>                <value>张三</value>            </entry>            <entry>                <key>                    <value>2</value>                </key>                <value>李四</value>            </entry>            <entry>                <key>                    <value>3</value>                </key>                <value>王五</value>            </entry>            <entry>                <key>                    <value>4</value>                </key>                <value>赵六</value>            </entry>        </map>    </property></bean>

4.4.properties 属性注入

<bean id="userServiceImpl" class="com.shsxt.service.impl.UserServiceImpl">    <property name="properties">            <props>                <prop key="a">test1</prop>                <prop key="b">test2</prop>            </props>    </property></bean>

遍历类似map
七、注解方式注入bean
对于bean的注入,除了使用xml 配置以外,注解的配置简化开发的速度,使程序看上去更简洁。对于注解的解释,spring对于注解有专门的解释器,对定义的注解进行解析,实现对应bean对象的注入,反射技术实现。
加入Aop jar包 spring-aop-4.3.2.RELEASE.jar
Xml 配置: 加入context命名空间 和xsd地址 并添加
context:annotation-config/> 配置

<?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">    <context:annotation-config/></beans>

对于bean的注入常用注解类型
@Autowired 属性字段或set方法上
@Resource 属性字段上或set方法上

区别: @Autowired 默认按bean 的类型匹配 可以修改 按名称匹配 和@Qualifier配合使用
@Resource 默认按名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行匹配注入,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
推荐使用@Resource 注解是属于J2EE的,减少了与spring 的耦合。

八、Spring Ioc容器自动扫描管理bean
实际的开发中,bean的数量非常多,采用手动配置bean的方式已无法满足生产需要,spring这时候同样提供了扫描的方式,对扫描到的bean对象统一进行管理,简化开发配置,提高开发效率。

<context:component-scan base-package="com.shsxt"/>

不需要再配置

<context:annotation-config/>

同时对于被spring 管理的bean 类的定义上需要加入对应的注解定义
开发中建议(开发中的一种约定)
Dao 层:@Repository
Service层:@Service
视图控制层:@Controller
如果对于开发的类实在不明确到底属于哪个层,可以使用@Component注解定义。
九、Bean的作用域问题
默认情况下,我们从spring容器中拿到的对象均是单例的,对于bean的作用域类型如下:
这里写图片描述

1、singleton 作用域
这里写图片描述

注意: lazy-init是懒加载, 如果等于true时作用是指spring容器启动的时候不会去实例化这个bean, 而是在程序调用时才去实例化. 默认是false即spring容器启动时实例化.

默认情况下,被管理的bean只会IOC容器中存在一个实例,对于所有获取该Bean的操作Spring容器将只返回同一个Bean。
容器在启动的情况下就实例化所有singleton 的 bean对象,并缓存与容器中
单例的好处:
1)提前发现潜在的配置问题
2)Bean 对象存在于缓存中,使用时不用再去实例化bean,加快程序运行效率
什么类型的对象适合作为单例对象来使用呢? service,dao,action等
一般来说对于无状态或状态不可改变的 对象适合使用单例模式(什么是无状态或状态不可改变)
实际上对象状态的变化往往均是由于属性值得变化而引起的,比如user类 年龄属性会有变化 属性年龄的变化一般会引起user对象状态的变化。对于我们的程序来说,无状态对象 没有实例变量的存在,保证了线程的安全性,service 层业务对象即是无状态对象。线程安全的。

2、prototype 作用域
这里写图片描述

通过scope=” prototype” 设置bean的类型 ,每次向Spring容器请求获取Bean都返回一个全新的Bean,相对于“singleton”来说就是不缓存Bean,每次都是一个根据Bean定义创建的全新Bean。

2、Web应用中的作用域(request、session、globalsession)
request作用域:表示每个请求需要容器创建一个全新Bean。比如提交表单的数据必须是对每次请求新建一个Bean来保持这些表单数据,请求结束释放这些数据。
session作用域:表示每个会话需要容器创建一个全新Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,
此时可以将该Bean配置为web作用域。
globalSession:类似于session作用域,只是其用于portlet(Portlet是基于Java的Web组件,由Portlet容器管理,并由容器处理请求,生产动态内容)环境的web应用。如果在非portlet环境将视为session作用域。
配置方式和基本的作用域相同,只是必须要有web环境支持,并配置相应的容器监听器或拦截器从而能应用这些作用域,我们会在集成web时讲解具体使用,大家只需要知道有这些作用域就可以了。
3、自定义作用域
在日常程序开发中,几乎用不到自定义作用域,除非又必要才进行自定义作用域。只做了解即可
十。Bean的生命周期
1.Bean的定义
对比已经学过的servlet 生命周期(容器启动装载并实例化servlet类,初始化servlet,调用service方法,销毁servlet)。
同样对于spring容器管理的bean也存在生命周期的概念
在Spring中,Bean的生命周期包括Bean的定义、初始化、使用和销毁4个阶段
在Spring中,通常是通过配置文档的方式来定义Bean的。在一个配置文档中,可以定义多个Bean。
2、Bean 的初始化
Spring bean 初始化有两种方式:
I.在配置文档中通过指定 init-method 属性来完成。
II.实现org.springframework.beans.factory.InitializingBean接口。
Bean对象实例化过程是在spring容器初始化时被实例化的,但也不是不可改变的,可以通过 lazy-init=”true” 属性延迟bean对象的初始化操作,此时再调用getbean 方法时才会进行bean的初始化操作

<bean id="userServiceImpl"class="com.shsxt.service.impl.UserServiceImpl"init-method="init"  >

3.Bean 的使用
I.使用BeanFactory
II.使用ApplicationContext
4.Bean的销毁
实现销毁方式(spring容器会维护bean对象的管理,可以指定bean对象的销毁所要执行的方法)

<bean id="userServiceImpl"class="com.shsxt.service.impl.UserServiceImpl" init-method="init" destroy-method="destroy"></bean>

通过AbstractApplicationContext 对象,调用其close方法实现bean的销毁过程。

AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("spring-application.xml");ctx.close();
0 0