Spring 笔记(一)

1.Spring概述

①Spring是一个开源框架
②Spring为简化企业级开发而生,使用Spring,JavaBean就可以实现很多以前要靠EJB才能实现的功能。同样的功能,在EJB中要通过繁琐的配置和复杂的代码才能够实现,而在Spring中却非常的优雅和简洁。
③Spring是一个IOC(DI)和AOP容器框架。
④Spring的优良特性

[1] 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
[2] 依赖注入:DI——Dependency Injection,反转控制(IOC)最经典的实现。
[3]面向切面编程:Aspect Oriented Programming——AOP
[4] 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
[5]组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
[6]一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。

⑤Spring目前的版本

⑥Spring模块
在这里插入图片描述
Test:Spting:单元测试块
Core Contaier:核心容器(IOC)
AOP +Aspecets(面向切面编程)

2.安装Spring插件

①插件包:springsource-tool-suite-.4.0.RELEASE-e4.3.0-updatesite.zip
②操作步骤:参照《参考资料:Spring插件安装图解.pptx》

3.搭建Spring运行时环境

①加入JAR包
[1]Spring自身JAR包:spring-framework-4.0.0.RELEASE\libs目录下
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
[2]commons-logging-1.1.1.jar

②根据需要创建Spring配置文件

4.1 Spring概图

在这里插入图片描述
IOC:(Inversion of Control)控制翻转
控制:资源的获取方式;
主动式:(要什么资源自给创建)

BookServlet{
	BookService bs = new BookService();// spring可以自动提供
	AirPlan ap= new AirPlan();//复杂对象的创建是比较庞大的工程
}

被动式:资源获取不是我们程序员自给创建,而是交给容器来创建
容器:管理所有的组件(有功能的类);容器可以自动探查出哪些组件(即类,需要用到哪另一些组件)
如下面的被冻死,容器可以自动帮我们使用Bookservice()类穿件 bs 对象;
本质:主动的new 到自动的生成

BookServlet{
	BookService bs;	
}

DI:()ependency Injection) 依赖注入;
容器可以自动探查出哪些组件(即类,需要用到哪另一些组件),然后通过反射的形式,将容器准备好的BookService对象注入(利用反射给属性赋值)到BookServlet;
只要容器管理的组件,都能使用容器提供的强的功能

通过各种方式给容器中注册对象
1IOC和DI
①IOC(Inversion of Control):反转控制。

在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取
所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源
的获取方式,增加了学习成本,同时降低了开发效率。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的
获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容
器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学
习成本,提高了开发的效率。这种行为也称为查找的被动形式。

②DI(Dependency Injection):依赖注入。
IOC的另一种表述方式:即组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器的资源注入。相对于IOC而言,这种表述更直接。

③IOC容器在Spring中的实现

  • [1]在通过IOC容器读取Bean的实例之前,需要先将IOC容器本身实例化。
  • [2]Spring提供了IOC容器的两种实现方式
  • (1)BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的。
  • (2)ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory。

④ApplicationContext的主要实现类

  • [1]ClassPathXmlApplicationContext:对应类路径下的XML格式的配置文件
    [2]FileSystemXmlApplicationContext:对应文件系统中的XML格式的配置文件
    [3]在初始化时就创建单例的bean,也可以通过配置的方式指定创建的Bean是多实例的。

ConfigurableApplicationContext

  • [1]是ApplicationContext的子接口,包含一些扩展方法 [2]
    refresh()close()让ApplicationContext具有启动、关闭和刷新上下文的能力。

WebApplicationContext
专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作

一、 实验:简单程序

1.先导包14.14 .6分
目标:使用Spring创建对象,为属性赋值
创建Student类

  1. 创建Spring配置文件Spring Bean Configuration File
    Spring配置文件中,集合了spring的ioc容器的所有组件

(1) Person.java

public class Person{
	private int age;
	public int getAge(){
	return age;
	}
	public int setAge(int age){
	this.age = age;
	}

}

spring配置文件

(2) Spring.xml

<!--注册一个Person 对象,Spring以后会自动创建Person类对象 -->

<beans>
<!--一个bean对应一个组件-->
<!--class属告诉Spring该组件,必须属性值是该组件的全类名,即将类注册进容器-->
<!--给个id,唯一标识,标识该对象-->
<!-- 使用property子元素为bean的属性赋值,即为该组件中的成员赋值 -->
	<bean id="numbe_1" class="com.atguigu.bean.Person">
		<property name="age" value="45"/>	
		<property>这个标签作用就是调用JavaBean中的get和set方法来赋值的
	</bean>
</beans>

(3) test.java

inport stativ prg.junit.Asser.*;
import org.junit.Text;//text文件里面写了 4个核心导入包的,导入语句
import org.springframework.context.ApplicationContext;

public classs IOCTest{
	/**
	*从容器中拿来组件
	*/
	public void test{
	//Application就是个接口,代表IOC容器
	//当前应用的配置文件在ClassPath下
	//得到容器对象 ioc
	ApplicationContext ioc = new ClassPathXmlApplicationContext("配置文件");
	/*
	1.上面是使用类路径下new出来
	2.当然也可以用FileSystemXmlAppliscationContext("文件路径")
	3.容器中的组件对象的创建,在容器对象创建完成后就已经创建了,所以容器一启动,里面所有的组件都会被创建,且是单实例
	4.容器没有指定的组件,如果去创建组件对象,那会报错
	5.Person 类中的成员是根据组件注册时候属性值赋值的,如:age=45
	*/
	Person bean = (Person) ioc.getBean("person1");//根据组件id,得到person对象
	System.out.println(bean);
	}
}

④测试:通过Spring的IOC容器创建Student类实例
⑤验证:Spring在创建IOC容器对象时,就已经完成了bean的创建和属性的赋值。

二、实验:根据组件类型,获取IOC容器中的组件

一.通过类型获取bean

  1. 从IOC容器中获取bean时,通过bean的类型获取。但如果同一个类型的bean在XML文件中配置了多个,则获取时会抛出异常,所以同一个类型的bean在容器中必须是唯一的。
    如:下面根据bean类型即Person 组件名来获取组件,如果 IOC 里面有Person1,Person2,那么会报错
@Test
public void test02{
Person bean = ioc.getBean(Person.class);
  1. 通过id值获取
@Test
public void test02{
Person bean = ioc.getBean("person1",Person.class);

三、实验:给组件的属性赋值

3.1赋值的途经
(1)通过bean的setXxx()方法赋值
实验一中使用的就是这种方式

(2)通过bean的构造器赋值

(1) Person02.java

public class Person02{
	private int age;
	public int getAge(){
	return age;
	}
	public int setAge(int age){
	this.age = age;
	}
	//构造器
	public Person02(int age)
	this.age= age;
}

(2) Spring.xml

(2.1)constructor-arg 标签
通过调用有参构造器给 组件对象赋值

     <bean id="book" class="com.atguigu.spring.bean.Person" >
           <constructor-arg name"age" value= "45"/>
 
     </bean >

(2.2)通过索引值指定参数位置:index=“从0开始的参数位置”

     <bean id="person1" class="com.atguigu.spring.bean.Book" >
           <constructor-arg value= "10010" index ="0"/>
         
     </bean >

(2.3)通过类型不同区分重载的构造器,防止混淆报错

(3) Person03.java

public class Person03{
	private int age;
	private int name1;
	private String name;
	public int getAge(){
	return age;
	}
	public int setAge(int age){
	this.age = age;
	}
	//构造器
	public Person03(int age,String name){
	this.age= age;
	this.name= name;
	}
	//重载
	public Person03(int age,int name){
	this.age= age;
	this.name1= name;
	}
}

(4) Spring.xml

假设我要第一个构造器的对象,则需要下面这么做

<bean id="book" class="com.atguigu.spring.bean.Book" >
      <constructor-arg value= "10010" index ="0" type="java.lang.Integer" />
      <constructor-arg value= "Book01" index ="1" type="java.lang.String" />

</bean >

(3)p名称空间

  • 防止标签重复,相当于包;为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。
  • Spring从2.5版本开始引入了一个新的p命名空间,可以通过元素属性的方式配置Bean的属性。
  • 使用p命名空间后,基于XML的配置方式将进一步简化。

先导入P命名空间

<bean 
	id="studentSuper" 
	class="com.atguigu.helloworld.bean.Person03"
	p:name="zhangshang" p:age="16">
</bean>

四、实验:正确的为各种属性赋值

(1)字面量

  • [1]可以使用字符串表示的值,可以通过value属性或value子节点的方式指定
  • [2]基本数据类型及其封装类、String等类型都可以采取字面值注入的方式
  • [3]若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来

(1) JB: Book.java

这是JavaBean,所有都有get,set,和toString,下面省略不写了

public class Book01{
	private String bookname;
	private int price;
//复杂类型
	private Car car
	private list<Car> cars;
	private Map<String,object> map;
	private Properties properties;

}

(2)JB: Car.java

public class Car{
	private String carName;
	private String color;
}

(2)null值
如果没直接赋值,那么对象的所有属性都是真 null 值,
如果直接 value=“null” 那么是假null值,除非用null标签

(3)ref 引用外部已声明的bean

(3)Spring.xml

因为组件Book中需要用到组件Car,所以Car需要先在spring中先注册
<beans>
	<bean class="com.atgigu.bean.Car" id="Car01">
	       <property name="carName" value="宝马"> </property>
	       <property name="color" value="green"> </property>
	</bean>
	
	<bean class="com.atguigu.spring.bean.Book" id="Book" >
	       <property name="bookName">
	          <null/>
	       </property>
	       <property name="price" value="50"/> </property>
	       <property name="Car" ref="Car01"></property>
	 </bean >
</beans>

(4) 省略 test.java

—————————————————————————————————————————————

(4)内部bean

  • 当bean实例仅仅给一个特定的属性使用时,可以将其声明为内部bean。
  • 内部bean声明直接包含在或元素里,不需要设置任何id或name属性
  • 内部bean不能使用在任何其他地方

Spring.xml

背部对car对象属性赋值,相当于内部 new 个car

<bean class="com.atguigu.spring.bean.Book" id="bookNull" >
    <property name="bookName">
      <null/>
    </property>
    <property name="price" value="50"/> </property>
	<property name='car'>
		<bean class= "com.atguigu.spring.bean.Car" >
    		<property name= "carName" value ="奔驰"/>
   			<property name= "color" value="black" />
		</bean>
    </property>
</bean >

(5)集合属性赋值
在Spring中可以通过一组内置的XML标签来配置集合属性,例如:,或

5.1 List

(1) Spring.xml

<beans>
<!--注册Book类 这个组件进容器并给设置id-->
<bean class="com.atguigu.spring.bean.Book" id="Book" ></bean>
<bean class="com.atgigu.bean.Car" id="Car01">
	       <property name="carName" value="宝马"> </property>
	       <property name="color" value="green"> </property>
</bean>
<!-- cars是个car 类型的list集合放在 类Book 中-->
<!--使用id为Book 的组件,并创建对象-->
<bean id="Book" class="com.atguigu.spring.bean.Book" >
           <property name="cars">
               <list>
               		<!-- 内部bean,相当于new ,是个新组件了 -->
               		<bean  class="com.atguigu.spring.bean.Car" p:carName="奔驰" p:color="black">
               		</bean>
              		 <!-- 外部引用 -->
               		<ref bean="Car01"/>
               		
               </list>
           </property>
</bean>         

(2) test.java

public void test(){
	Book book01= (Book) ioc.getBean("Book");
	System.out.println(car);
	List<Car> cars = book01.getCars();
	System.out.println(cars);

结果

[宝马,白色] [奔驰,黑色]

5.2 Map

<property name="map">
	<!--map = new LinkedHashMap()内部map-->
	<map>
	<!--一个entery标签代表一个键值对-->
		<entery key="1" value="zhangsan"></entery>
		<entery key="2" value="lisi"></entery>
	<!--下面演示,map集合的值是对象的情况,分为内部bean和外部bean-->
		<entery key="3" value-ref="Car01"></entery>
		<entery key="4" >
			<bean  class="com.atguigu.spring.bean.Car" p:carName="奔驰" p:color="black">
            </bean>
		</entery>
	</map>       
</property>

5.3 Properties

使用定义java.util.Properties,该标签使用多个作为子标签。每个标签必须定义key属性

(3) Spring.xml

<bean class="com.atguigu.spring.bean.Book" id="Book">
<!-- private Properties properties; -->
<property name="properties">
	<pros>
		<prop key="username">root</prop>
		<prop key="password">1234</prop>
	</pros>
</property >
</bean>

5.4 util名称空间创建 集合类型的bean,方便使用

不能用别人的内部map,所以试着用util名称空间
同理 list 也可以用util 集合

<beans> 
	<bean class="com.atguigu.spring.bean.Book" id="Book">
		<!-- private Properties properties; -->
		<property name="map" ref="myMap"></property>
	</bean>
</beans>
<!-- 这里相当于已经new个map了-->
<util:map id="myMap">
	<entery key="1" value="zhangsan"></entery>
	<entery key="2" value="lisi"></entery>
	<!--下面演示,map集合的值是对象的情况,分为内部bean和外部bean-->
	<entery key="3" value-ref="Car01"></entery>
	<entery key="4" >
		<bean  class="com.atguigu.spring.bean.Car" p:carName="奔驰" p:color="black">
	     </bean>
    </entery>
</util:map>

5.5 给bean的级联属性赋值
级联属性:比如我们的Car类 中的 carNamae 属性是 Book 类 中属性Car的属性
级联属性使用要注意:如果其他是 ref 引用的,也是借用地址实现,所以改变级联属性的值,原来的引用者的值也会被改变

<beans>
<bean class="com.atguigu.spring.bean.Book" id="Book" ></bean>
<bean class="com.atgigu.bean.Car" id="Car01">
	       <property name="carName" value="宝马"> </property>
	       <property name="color" value="green"> </property>
</bean>
<bean id="Book" class="com.atguigu.spring.bean.Book">
	<!--为car 赋值改变car的颜色-->
	<property name="car" ref="Car01"></property>
	<property name="car.color" valu="blue"></property>
</bean>
</beans>

六、实验:通过继承实现bean配置信息的重用

配置重用 :比如下面的 Car03跟 Car02 属性一直,唯独汽车名字不同,那我们可以让
Car03 继承 Car02

<bean id="Car02" class="com.atgigu.bean.Car" >
	 <property name="carName" value="大众"> </property>
	  <property name="color" value="yellow"> </property>
</bean>

<bean id="Car03" class="com.atgigu.bean.Car" parent="Car02">
	 <property name="carName" value="现代"> </property>
</bean>

七、实验:通过abstract 属性创建一个模板bean

模板不能被获取对象,只能用来继承

<bean id="Car02" class="com.atgigu.bean.Car" abstract="ture" >
	 <property name="carName" value="模板"> </property>
	  <property name="color" value="模板"> </property>
</bean>

八、实验:bean 之间的依赖

依赖:指改变对象创建顺序

New.xml

<bean id="car" class="com.atgigu.bean.Car" depends-on="book,person"></bean>
<bean id="book" class="com.atgigu.bean.Book"></bean>
<bean id="person" class="com.atgigu.bean.Person"></bean>

九、实验:测试bean的作用域,分别创

建单实例和多实例的bean
作用域:指bean是否范实例;默认为单实例
prototype:多实例,容器启动不会自动创建,除非在获取

的时候才会创建;且每次调用都是重新创建的
singletion:单实例,在容器启动完成之前已经创建好对象,且保存在容器中;任何时候获取,都是使用之前创建好的
request:在web环境下,同一次请求创建bean实例
session:在web环境下,同一次会话创建bean实例

多实例举例:
Car.java

public void Car{
	Car(){
		System.out.println("car被创建了");
		}
}

spring.xml


<bean id="car" class="com.atgigu.bean.Car scope=" prototype"></bean>

结果

car被创建了
car被创建了

五、 实验5 配置通过静态工厂方法创建bean,实例工厂方法创建bean,FactoryBean

有简便书写的作用

  • 原来 bean的创建默认是框架利用反射new出来的bean 实例
  • 工厂模式:工厂帮我们创建对象(即有一个类帮我们创建对象,这个类叫做工厂)
  • 静态工厂:工厂本身不用创建对象,都是通过静态方法调用:工厂类.工厂方法名
  • 实例工厂:工厂本事需要创建对象, new工厂类():
 工厂类  工厂对象 = new 工厂类();
 工厂对象.getAirPlane("haha");

(1) 实例工厂.java

package.com.atguigu.factory;
import com.atguigu.bean.AirPlane;

public class AirPlaneInstanceFactory{
	public static AirPlane getAirPlane(String jzName){
		AirPlane airPlane = new AirPlane();
		airPlane.setFdj("太行");
		airPlane.setJzName(jzName);
		airPlane.setFjzName("张三"); 
	}
}

(2) 静态工厂.java

package.com.atguigu.factory;
import com.atguigu.bean.AirPlane;

public class AirPlaneStaticFactory{
//直接在静态工厂里面就直接造飞机了,不用new 工厂
	public static AirPlane getAirPlane(String jzName){
		AirPlane airPlane = new AirPlane();
		airPlane.setFdj("太行");
		airPlane.setJzName(jzName);
		airPlane.setFjzName("张三"); 
	}
}

调用静态工厂类,不用创建工厂对象,且指定调用工厂里面的方法

<bean 
id="airPlane01" 
class="com.atguigu.factory.AirPlaneStaticFactory"
factory-method="getAirPlane">
	<!--可以为方法指定参数-->
	<constructor-arg value="李四"></constructor-arg>
</bean>

调用实例工厂类

  1. 先配置实例工厂对象
  2. 再配置我们要创建的AirPlane使用哪各工厂实例
  3. factory-bean 指定当前对象创建使用哪个工厂
创建工厂对象
<bean id="InstanceFactory"
	  class="com.atguigu.factory.AirPlaneInstanceFactory">
</bean>
创建飞机对象,并使用工厂
<bean 
id="airPlane02" 
class="com.atguigu.factory.AirPlane"
factory-bean="AirPlaneInstanceFactory"
factory-method="getAirPlane">
	<!--可以为方法指定参数-->
	<constructor-arg value="李四"></constructor-arg>


</bean>

FactoryBean是Spring定义的一个接口

注意:他可以调控是否为单实例和多实例
作用:只要都是这个接口的实现类,那么spring都认为是工厂对实例
spring会自动调用工厂方法创建对象
spring.xml
会自动帮你去MyFactorBeanImple调用 getOBject方法来返回对象
(要是上面的话,就没有自动了,这就是区别之处)

<bean 
id="myFactoryBeanImple"
class="com.atguigu.factory.MyFactorBeanImple">
</bean>

myFactoryBeanImple.java

package.com.atguigu.factory;
import org.springframework.beans.factory.FactoryBean;
import com.atguigu.bean.Book;
/*
 *编写一个FactoryBean的实现类
 在spring 配置文件中进行注册
*/
public class MyFactorBeanImple implements FactoryBean<Book>{
/*
	* 工厂方法
	* 返回创建对象
*/
	public Book getOject()throw Exception{
		Book book = new Book();
		book.setBookName(UUID.randoUUID().toString());
	return book;
	}
/*
 * 返回创建对象的类型
 * spring会自动调用这个方法确认创建对象是什么类型
*/
	public Class<?> getObjectType(){
	return null;
	}
/*
 *返回是否为单列
*/
	public boolen isSingletion{
		return false;//不是单实例
	}
}

test.java

private ApplicationContext ioc = new ClassPathXmlApplicationContext("配置文件");
public void test(){
		Object bean = ioc.getBean("myFactoryBeanImple")
//此时bean 就是 book 对象了

过程:通过寻找id → 因为他是FactoryBean的实例类 → 知道他是工厂类
→ 自动调用里面的 getObject 方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值