Spring 学习 (一)

Spring 学习 (一)

目录

什么是Spring

Spring的优点

Spring 核心之 IoC(控制反转)

什么是IOC(控制反转)?

什么是DI(依赖注入)

IOC和DI区别

Spring工厂类

Spring工厂类的结构图

BeanFactory:老版本的工厂类

ApplicationContext:新版本的工厂类

Bean的相关的配置

Spring实例化bean的三种方式

1.默认构造方法(最常用的初始化bean方式, 必须提供默认构造方法)

2.静态工厂初始化bean

3.实例工厂初始化bean

Spring的属性注入

构造方法的方式的属性注入

Set方法的方式的属性注入

 

P名称空间的属性注入(Spring2.5以后)

SpEL的属性注入(Spring3.0以后)

集合类型属性注入(了解)

分模块配置(怎么使用多个配置文件)


什么是Spring


Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

Spring的优点

Spring 核心之 IoC(控制反转)

首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinnianshilongnian.iteye.com/blog/1413846

什么是IOC(控制反转)?

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

  ●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  ●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

  用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:

               图1-1 传统应用程序示意图

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:

       图1-2有IoC/DI容器后程序结构示意图

以下分享其它博客的通俗讲解:

所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。

  那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

什么是DI(依赖注入)

  IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的

依赖注入:前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。

<!--Spring入门的配置  -->
<bean id="userDao" class="com.ysx.spring.demo1.UserDaoImpl">
</bean>

这是正常情况下,将class对应的类交给Spring管理,那DI就是下面这种引入class类中属性的情况

<!--Spring入门的配置  -->
<bean id="userDao" class="com.ysx.spring.demo1.UserDaoImpl">
        <property name="name" value="李东"></property>
</bean>

当Spring帮我们创建这个UserDaoImpl类的对象时发现这个类中有一个属性name,这叫依赖。通过这里<property>帮我们把属性设置进来这就叫依赖注入也就是DI

依赖:下面代码块中,B类运行需要调用A类对象作为参数,我们就可以说B依赖A

Class A{

}

Class B{
    public void xxx(A a){
   
    }
}

IOC和DI区别

IOC:控制反转,将类的对象创建权交给Spring管理

DI:在Spring管理这个类的过程当中将这个类的属性设置进来

 

Spring工厂类

我们还是通过实例来讲解怎么使用:

首先设置接口

/**
 * -用户管理业务层的接口
 * @author hp
 *
 */
public interface UserDao {
	public void save();
}

 

然后是接口实现类

/**
 * -用户管理业务层的接口实现类
 * @author hp
 *
 */
public class UserDaoImpl implements UserDao {
	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public void save() {
		// TODO Auto-generated method stub
		System.out.println("UserService执行了。。。" + name);
	}
}

​

然后我们创建一个配置文件applicationContext.xml(Spring的默认名字,你叫什么都行)

这个 xml 文件的 beans 的 schema

<?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">
	
</beans>

然后我们在里面写入<bean>标签

<?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">
	
	<!--Spring入门的配置  -->
    
    id    是bean标签的唯一标识名字,自己起的
    class 中是要让Spring管理的类的全限定名

    property  是DI给类的属性赋值
    name      是类中属性的属性名
    value     是属性的值

	<bean id="userDao" class="com.ysx.spring.demo1.UserDaoImpl">
		<property name="name" value="李东"></property>
	</bean>
	
</beans>

最后写一个测试类

public class SpringDemo1 {

	@Test
	public void demo2() {

		//创建Spring的工厂 applicationContext
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");  
		UserDao userDao = (UserDao) applicationContext.getBean("userDao");
		userDao.save();
	}
}

我们可以看到工厂类的名字是ApplicationContext

 

Spring工厂类的结构图

我们可以从图中看到 ApplicationContext 继承 BeanFactory

BeanFactory:老版本的工厂类

在上例中如果工厂类是 BeanFactory 只有调用getBean的时候,才会生成类的实例

ApplicationContext:新版本的工厂类

ApplicationContext工厂类在加载配置文件的时候,就会将Spring管理的类都实例化。(它是BeanFactory的子类,意味着它的功能更加强大)

ApplicationContext有两个实现类
ClassPathXmlApplicationContext    :加载类路径下的配置文件
FileSystemXmlApplicationContext    :加载文件系统下的配置文件

Bean的相关的配置

<bean>标签的id和name的配置

id : 使用了约束中的唯一约束。里面不能出现特殊字符的。

name : 没有使用约束中的唯一约束(理论上可以出现重复的,但是实际开发不能出现的)。里面可以出现特殊字符。Spring和Struts1框架整合的时候会用到name,平常就用 id就可以了

Bean的生命周期的配置(了解)

init-method           :Bean被初始化的时候执行的方法

destroy-method    :Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭)

        <!-- Spring生命周期的配置  -->
	<bean id="customerDAO" class="com.ysx.spring.demo2.CustomerDAOImpl" scope="singleton" 
init-method="setup" destroy-method="destroy">
	
	</bean>

两个里面都直接写class对应类的方法名即可

这里我们还看到有一个scope的属性,这就涉及到我们的下一个知识点也是最重要的一个重点

Bean的作用范围的配置(重点)

    scope :Bean的作用范围

范围包括:

  1. singleton        :默认的,Spring会采用单例模式创建这个对象。
  2. prototype        :多例模式。(Struts2Spring整合一定会用到)
  3. request             :应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中。
  4. session             :应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中。
  5. globalsession   :应用在web项目中,必须在porlet环境下使用。但是如果没有这种环境,相当于session。

porlet环境什么?       就是联合网站免登陆,比如当你登录百度官网,再到其子网站比如百度文库,百度贴吧都不用再进行登录操作,这种就用到了globalsession属性。

Spring实例化bean的三种方式

默认构造方法

静态工厂方法

实例工厂方法

1.默认构造方法(最常用的初始化bean方式, 必须提供默认构造方法

 

public class Person {

    private String name;
    private Integer age;

    public Person() {
        System.out.println("这是一个无参构造函数");
    }

    public Person(String name) {
        this.name = name;
        System.out.println(name+"参数的构造函数");
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("带有名字="+name+"和年龄="+age+"参数的构造函数");
    }

}

bean.xml

<bean id="person" class="com.maple.Person"></bean>
<bean id="personWithParam" class="com.maple.Person">
    <constructor-arg name="name" value="枫叶"/>
</bean>
<bean id="personWirhParams" class="com.maple.Person">
        <constructor-arg name="name" value="枫叶"/>
        <constructor-arg name="age" value="23"/>
</bean>

2.静态工厂初始化bean

当采用静态工厂方法创建bean时,除了需要指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法。Spring将调用此方法返回实例对象,就此而言,跟通过普通构造器创建类实例没什么两样。

public class MyBeanFactory {
    
    /**
     * 创建实例
     * @return
     */
    public static UserService createService(){
        return new UserServiceImpl();
    }
        
        public static UserService createService(String name){
        return new UserServiceImpl(name);
    }

        public static UserService createService(String name,int age){
        return new UserServiceImpl(name,age);
    }
}

bean.xml

<bean id="userServiceId" class="com.maple.MyBeanFactory" factory-method="createService"></bean>
<bean id="userServiceId" class="com.maple.MyBeanFactory" factory-method="createService">
    <constructor-arg name="name" value="枫叶"/>
</bean>
<bean id="userServiceId" class="com.maple.MyBeanFactory" factory-method="createService">
    <constructor-arg name="name" value="枫叶"/>
    <constructor-arg name="age" value="23"/>
</bean>

3.实例工厂初始化bean

与使用静态工厂方法实例化类似,用来进行实例化的非静态实例工厂方法位于另外一个bean中(即下面的MyBeanFactory .java),容器将调用该bean的工厂方法来创建一个新的bean实例。

为使用此机制,class属性必须为空,而factory-bean 属性必须指定为当前(或其祖先)容器中包含工厂方法的bean的名称,而该工厂bean的工厂方法本身必须通过factory-method属性来设定。
必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。

/**
 * 实例工厂,所有方法非静态
 *
 */
public class MyBeanFactory {
    
    /**
     * 实例化工厂
     */
    public UserService createService(){
        return new UserServiceImpl();
    }
        
        /**
     * 实例化工厂1
     */
        public static UserService createService(String name){
        return new UserServiceImpl(name);
    }
        
        /**
     * 实例化工厂2
     */
        public static UserService createService(String name,int age){
        return new UserServiceImpl(name,age);
    }

        
}

bean.xml

<!-- 创建工厂实例 -->
    <bean id="myBeanFactoryId" class="com.maple.MyBeanFactory"></bean>
    <!-- 获得userservice 
        * factory-bean 确定工厂实例
        * factory-method 确定普通方法
    -->
    <bean id="userServiceId" factory-bean="myBeanFactoryId" factory-method="createService"></bean>

        <bean id="userServiceId" factory-bean="myBeanFactoryId" factory-method="createService">
                       <constructor-arg name="name" value="枫叶"/>
        </bean>

        <bean id="userServiceId" factory-bean="myBeanFactoryId" factory-method="createService">
                     <constructor-arg name="name" value="枫叶"/>
                     <constructor-arg name="age" value="23"/>
        </bean>

Spring的属性注入

构造方法的方式的属性注入

Set方法的方式的属性注入

Set方法的属性注入

Set方法设置对象类型的属性

这里的 ref 中的 car2 指向上面的 id为 car2 的<bean>标签然后调用该标签对Car2类对象进行属性注入再返还给下面的ref

P名称空间的属性注入(Spring2.5以后)

通过引入p名称空间完成属性的注入:

写法:

  1. 普通属性        p:属性名=”值”
  2. 对象属性        p:属性名-ref=”值”

P名称空间的引入

使用p名称空间

SpEL的属性注入(Spring3.0以后)

SpEL:Spring Expression Language,Spring的表达式语言。

语法 :   #{SpEL}

SpEL 字面量:

整数           :#{8}
小数           :#{8.8}
科学计数法:#{1e4}
String         :可以使用单引号或者双引号作为字符串的定界符号。
Boolean     :#{true}


SpEL引用bean , 属性和方法:

引用其他对象:#{car}
引用其他对象的属性:#{car.brand}
调用其它方法 , 还可以链式操作:#{car.toString()}
调用静态方法静态属性:#{T(java.lang.Math).PI}


 SpEL支持的运算符号:

算术运算符:+,-,*,/,%,^(加号还可以用作字符串连接)
比较运算符:< , > , == , >= , <= , lt , gt , eg , le , ge
逻辑运算符:and , or , not , |
if-else 运算符(类似三目运算符):?:(temary), ?:(Elvis)
正则表达式:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}

 

集合类型属性注入(了解)

当里面是普通类型,就用<value>标签

当里面是对象类型,就用<ref>标签

<!-- Spring的集合属性的注入============================ -->
	<!-- 注入数组类型 -->
	<bean id="collectionBean" class="com.itheima.spring.demo5.CollectionBean">
		<!-- 数组类型 -->
		<property name="arrs">
			<list>
				<value>王东</value>
				<value>赵洪</value>
				<value>李冠希</value>
			</list>
		</property>
		
		<!-- 注入list集合 -->
		<property name="list">
			<list>
				<value>李兵</value>
				<value>赵如何</value>
				<value>邓凤</value>
			</list>
		</property>
		
		<!-- 注入set集合 -->
		<property name="set">
			<set>
				<value>aaa</value>
				<value>bbb</value>
				<value>ccc</value>
			</set>
		</property>
		
		<!-- 注入Map集合 -->
		<property name="map">
			<map>
				<entry key="aaa" value="111"/>
				<entry key="bbb" value="222"/>
				<entry key="ccc" value="333"/>
			</map>
		</property>
	</bean>

分模块配置(怎么使用多个配置文件)

两种方法:

1.在加载配置文件的时候,加载多个

2.在一个配置文件中引入多个配置文件

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值