初学Spring笔记整理
- Spring简介
- Spring Bean 定义
- Spring Bean 作用域
- 例子:
- (1)用无参构造方法创建对象
- (2)用带参的构造方法创建对象
- (3)用静态工厂创建对象
- (4)用非静态工厂创建对象
- Spring的单例模式和多例模式
- Spring框架的依赖注入
- 依赖注入简介
- 依赖注入的类型:
- (1)setter方法注入:
- (2)调用带参的构造方式注入:
- (3)p名称空间注入:
- (4)spel表达式注入:
- 复杂类型注入
- (1)List是一种按照序号标识的集合
- (2)Set与List相似但是元素不允许重复
- (3)Map则是一种自定的键值对,键值都可以是任意的类型。
- Spring `property`标签中的 ref属性和ref 标签有什么不同?
Spring简介
1. Spring官网: http://spring.io/
Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,Spring是于2003年兴起的一个轻量级的Java开发框架。由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架
Spring是一个非常活跃的开源框架,基于IOC和AOP来构架多层JavaEE系统,以帮助分离项目组件之间的依赖关系。他的主要目的是简化企业开发。
简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架。高内聚低耦合!!!
Spring 春天、泉水! JAVAEE的春天来了!
Rod Johnson:
2. Spring的优点:
(1)IOC思想 方便解耦,简化开发
Spring就是一个大工厂,可以将所有对象创建和依赖的关系维护,交给Spring管理。
(2)AOP编程(面向切面编程)的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
(3)声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程 SSM、SSS、SSH。
(4)方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序,Spring-test:Spring 的测试模块!
(5)方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:Struts、Hibernate、MyBatis、Quartz(定时任务)等)的直接支持
Spring框架可以无缝缝合整合其他框架:Mybatis、Hibernate、Redis、Activiti、SpringMVC、SpringDATA…
只要是框架,那么Spring就可以管理
(6)降低JavaEE API的使用难度
Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
3、Spring体系结构
Spring框架至今已集成了20多个模块,这些模块分布在以下模块中:
核心容器(Core Container)
数据访问/集成(Data Access/Integration)层
Web层
AOP(Aspect Oriented Programming)模块
植入(Instrumentation)模块
消息传输(Messaging)
测试(Test)模块
Spring体系结构如下图:
Spring Bean 定义
Bean 定义:
被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的,例如,已经在先前章节看到的,在 XML 的表单中的 定义。
bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:
如何创建一个 bean
bean 的生命周期的详细信息
bean 的依赖关系
上述所有的配置元数据转换成一组构成每个 bean 定义的下列属性。
Bean标签的常用属性
属性 | 描述 |
---|---|
Id | 这个属性是标签起的名称,根据id值得到配置对象。 |
class | 这个属性是创建对象所在的全路径 |
name | 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符,name属性可以包含特殊符号。 |
scope | 这个属性指定由特定的 bean 定义创建的对象的作用域,设置类的特点。 |
Singleton | 默认的值,单例的,只能实例化一个对象。两个对象的话地址一样。 |
Prototype | 多例的,用户action的配置,action是多实例的 |
properties | 这个属性是它是用来注入依赖关系的 |
Request:web | spring创建一个bean对象,将对象存入到request中 |
autowiring mode | 这个属性是它是用来注入依赖关系的 |
lazy-initialization mode | 这个属性是延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。 |
initialization 方法 | 这个属性在 bean 的所有必需的属性被容器设置之后,调用回调方法。 |
destruction 方法 | 这个属性当包含该 bean 的容器被销毁时,使用回调方法。 |
destruction 方法 | 这个属性当包含该 bean 的容器被销毁时,使用回调方法。 |
Spring Bean 作用域
Bean 的作用域
当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton。
Spring 框架支持以下五个作用域,分别为singleton、prototype、request、session和global session,5种作用域说明如下所示,
注意,如果你使用 web-aware ApplicationContext 时,其中三个是可用的。
作用域 | 描述 |
---|---|
singleton | 根据Spring IoC容器将单个bean定义范围限定为单个对象实例。 |
prototype | 将单个bean定义范围限定为任意数量的对象实例。 |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境 |
global-session | 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境 |
例子:
1.新建一个Spring工程,配置pom.xml加载Spring依赖
<dependencies>
<!--加载依赖Spring-->
<dependencies>
<!--加载依赖Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
2.在resources资源文件夹下面创建一个applicationContext.xml
消除顶部的黄色的框框:
点击右上角Configgure application context,选择Create new application context…
点击OK即可消除
3.建立一个bean包定义一个Person.java类
属性有:
private int id;
private String name;
private String sex;
分别点出该类的无参构造方法,有参构造方法,toString方法,get、set方法。
**
(1)用无参构造方法创建对象
在applicationContext.xml配置文件:
<!--
class:表示对象从person类中创建,对象的路径
name 相当于小名,可以有多个
scope="singleton"单例(作用域,表示bean对应对象生成规则(默认为singleton))
scope="prototype"多例,new了多个统一对象new出来的对象是不一样的
lazy-init="true"表示对象加载时机:
(true:使用对象的时候才创建)
(false:Spring框架一启动就加载)
-->
<!-- 无参构造方法创建对象-->
<bean id="p1" name="person1,person2" class="com.swjd.bean.Person" scope="singleton" lazy-init="true"
init-method="init" destroy-method="destroy">
<!-- 依赖注入 -->
<property name="id" value="957"></property>
<property name="name" value="刘刘刘"></property>
<property name="sex" value="女"></property>
</bean>
在Test里面测试无参构造方法创建对象
public class MyTest {
public static void main(String[] args) {
//以前的方式
// Person person=new Person();
// person.setId("123");
// System.out.println(person);
//用Spring容器的方式
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.拿对象
Person person1=context.getBean("p1",Person.class);
System.out.println(person1);
}
测试结果:
(2)用带参的构造方法创建对象
在applicationContext.xml配置文件:
<!-- 方式二:用带参的构造方法创建对象-->
<!-- 当构造函数有多个参数时,
可以使用constructor-arg标签的index属性,
index属性的值从0开始。-->
<bean id="p3" class="com.swjd.bean.Person">
<constructor-arg index="0" type="int" value="9528"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="张三"></constructor-arg>
<constructor-arg index="2" type="java.lang.String" value="男"></constructor-arg>
</bean>
在Test里面测试有参构造方法创建对象
public class MyTest {
public static void main(String[] args) {
//用Spring容器的方式
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.拿对象
//测试带参数构造方法创建对象
Person person=context.getBean("p3",Person.class);
System.out.println(person);
}
}
测试结果:
(3)用静态工厂创建对象
首先建立一个beanfactory包定义一个PersonFactory.java类
在PersonFactory.java类创建person的静态方法
package com.swjd.beanfactory;
import com.swjd.bean.Person;
//静态工厂
public class PersonFactory {
//创建person的静态方法
public static Person createPerson(){
System.out.println("通过静态工厂创建对象");
return new Person(1234,"丽丝尔","女");
}
}
在applicationContext.xml中调用静态工厂的方法:
<!--方式三:用静态工厂创建对象 调用静态工厂的方法-->
<bean id="p4"
class="com.swjd.beanfactory.PersonFactory"
factory-method="createPerson">
</bean>
在Test里面测试静态工厂创建对象
public class MyTest {
public static void main(String[] args) {
//用Spring容器的方式
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//测试静态工厂方法创建对象
Person person=context.getBean("p4",Person.class);
System.out.println(person);
}
}
测试结果:
(4)用非静态工厂创建对象
首先在beanfactory包定义一个NoStaticPersonFactory.java类
在PersonFactory.java类创建person的静态方法
package com.swjd.beanfactory;
import com.swjd.bean.Person;
//静态工厂
public class NoStaticPersonFactory {
//创建person的静态方法
public Person createPerson(){
//System.out.println("通过非静态工厂创建对象");
return new Person(1234,"王五","男");
}
}
在applicationContext.xml配置文件:
<!--方式四:用非静态工厂创建对象
调用静态工厂的方法 不能直接调用静态工厂的方法,因为他的方法不带static 所以要id="noStaticFactory"-->
<bean id="noStaticFactory"
class="com.swjd.beanfactory.NoStaticPersonFactory">
</bean>
<bean id="p5" factory-bean="noStaticFactory"
factory-method="createPerson">
</bean>
在Test里面测试非静态工厂创建对象
public class MyTest {
public static void main(String[] args) {
//用Spring容器的方式
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//测试非静态工厂方法创建对象
Person person=context.getBean("p5",Person.class);
System.out.println(person);
测试结果:
Spring的单例模式和多例模式
spring的Bean默认的是单例的,Bean的作用域可以通过Bean标签的scope属性进行设置
默认情况下scope=“singleton”,那么该Bean是单例,任何人获取该Bean实例的都为同一个实例;
(1)scope=“prototype”,任何一个实例都是新的实例;
(2)scope=“request”,在WEB应用程序中,每一个实例的作用域都为request范围;
(3)scope=“session”,在WEB应用程序中,每一个实例的作用域都为session范围;
注意:在默认情况下,Bean实例在被Spring容器初始化的时候,就会被实例化,默认调用无参数的构造方法。在其它情况下,Bean将会在获取实例的时候才会被实例化。
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
Spring框架的依赖注入
依赖注入简介
依赖注入定义:
依赖注入(DI,DependencyInjection):依赖注入,也叫控制反转是Spring框架的核心机制,相当于心脏对于人的重要性,只有真正理解这些核心的功能,才有能力使用spring框架。它使spring框架核心IOC的具体体现吗,是表示在应用程序中表示层与层之间,对象与对象之间的关系。简单的说就是给类的成员变量赋值。
依赖注入主要作用: 依赖注入能够让相互协作的软件组件保持松散耦合
Spring中的依赖注入就是上面说的外部,实例不在由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类。 实例之间的依赖关系由IOC容器负责了,等待Spring依赖注入。
依赖注入的类型:
建立一个bean包定义一个Man.java类
属性有:
private int id;
private String name;
private int age;
分别点出该类的无参构造方法,有参构造方法,toString方法,get、set方法。
(1)setter方法注入:
就是通过set方法,给类的成员变量赋值。
在applicationContext.xml配置文件:
<bean id="m1" class="com.swjd.bean.Man">
<!--第一种依赖注入方式:通过setter方式注入-->
<property name="id" value="1"/>
<property name="name" value="刘刘刘"/>
<property name="age" value="18"/>
</bean>
在Test里面测试setter方法注入
package com.swjd.test;
import com.swjd.bean.Man;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//拿对象
System.out.println(context.getBean("m1", Man.class));
}
}
测试结果:
(2)调用带参的构造方式注入:
就是通过构造方法,给类的成员变量赋值
在applicationContext.xml配置文件:
<!--String是一个完整的包-->
<bean id="m2" class="com.swjd.bean.Man">
<constructor-arg index="0" type="int" value="2"/>
<constructor-arg index="1" type="java.lang.String" value="左本进"/>
<constructor-arg index="2" type="int" value="20"/>
</bean>
在Test里面测试带参的构造方式注入
package com.swjd.test;
import com.swjd.bean.Man;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//拿对象
System.out.println(context.getBean("m2", Man.class));
}
}
测试结果:
(3)p名称空间注入:
依赖注入简化配置
在applicationContext.xml配置文件:
<!--第三种依赖注入方式:p命名空间注入(注解方式注入对象)
p名称空间注入,说明:
第一步:导入p名称空间
xmlns:p="http://www.springframework.org/schema/p"
第二步:
p:属性名称 ==>给java简单类型成员变量赋值
p:属性名称-ref ==>给其他bean类型成员变量赋值
-->
<bean id="m3" class="com.swjd.bean.Man"
p:id="3" p:name="张三" p:age="25" >
</bean>
在Test里面测试p名称空间注入
package com.swjd.test;
import com.swjd.bean.Man;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//拿对象
System.out.println(context.getBean("m3", Man.class));
}
}
测试结果:
(4)spel表达式注入:
在applicationContext.xml配置文件:
<!--第四种依赖注入方式:spel表达式注入-->
<bean id="m4" class="com.swjd.bean.Man">
<property name="id" value="#{m1.id}"></property>
<property name="name" value="#{m2.name}"></property>
<property name="age" value="#{m3.age}"></property>
</bean>
在Test里面测试spel表达式注入
package com.swjd.test;
import com.swjd.bean.Man;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//1.启动并加载Spring框架 括号里面写我要启动的是谁
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext.xml");
//拿对象
System.out.println(context.getBean("m4", Man.class));
}
}
测试结果:
复杂类型注入
对于程序员来说,掌握多种语言是基本的技能。
我们这里做了一个小例子,程序员们是一个Bean实例,而掌握的编程语言则是放入一个集合类型中进行注入。
简单的来说:
(1)List是一种按照序号标识的集合
(2)Set与List相似但是元素不允许重复
(3)Map则是一种自定的键值对,键值都可以是任意的类型。
在bean包定义一个Student.java类
属性有:
private String name;
private String[] hobbies;//爱好
private List<String> subject;//科目
private Map<String,Object> map;
分别点出该类的无参构造方法,有参构造方法,toString方法,get、set方法。
在resources资源文件夹下面创建一个applicationContextStu.xml
在applicationContextStu.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">
<!-- 复杂类型注入-->
<!-- 用set注入-->
<bean id="s1" class="com.swjd.bean.Student">
<property name="name" value="刘高高"/>
<property name="hobbies" >
<!-- 数组 -->
<array>
<value>唱歌</value>
<value>跳舞</value>
<value>学习</value>
</array>
</property>
<!-- list集合-->
<property name="subject">
<list>
<value>Spring</value>
<value>MyBatis</value>
<value>Android</value>
</list>
</property>
<!-- map集合-->
<property name="map">
<map>
<entry key="CN">
<value>中国</value>
</entry>
<entry key="RU">
<value>俄罗斯</value>
</entry>
</map>
</property>
</bean>
</beans>
在Test里面测试s复杂类型注入
package com.swjd.test;
import com.swjd.bean.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestStu {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=
new ClassPathXmlApplicationContext("applicationContext-stu.xml");
System.out.println(context.getBean("s1", Student.class));
}
}
测试结果:
Spring property
标签中的 ref属性和ref 标签有什么不同?
spring property标签中的 ref属性和ref 标签有什么不同? 如下:
<property name="a" ref="b" />
和
<property name="a" >
<ref bean="b" />
</property>
这两种方式有啥不一样的?
Spring的配置文件可能会有多个
<property name="a" ref="b" />
就是找当前配置文件里的bean 也就是b
<ref bean ="b"/>
是寻找全局中的 bean;