spring的第一天
spring的第一天
Spring是什么?
Spring是容器框架,用来配置(装)Bean,并且维护Bean之间的关系。其中Bean可以是Java中的任何一种对象,可以是JavaBean,Service,Action或者是DAO。
Spring的基础
Spring有2个重要的概念IOC(控制反转)
和DI(依赖注入)
。
-
IOC控制反转
-
谁控制谁,控制什么:
在以前的程序设计中,我们都是使用
new
来创建对象,是程序主动去创建依赖对象。而在IOC中有一个容器来创建对象,变成了由IOC控制对象的创建。于是IOC控制了对象和资源文件。 -
反转
依赖对象的获取反转了。
-
-
依赖注入DI
IOC的一个重点是在系统中运行中,动态的向某个对象提供它所需要的其他对象,这一点就是通过DI(Dependency Injection,依赖注入)实现的。
Spring的框架
spring的核心模块
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
1)Spring Core:核心容器,BeanFactory提供了组件生命周期的管理,组件的创建,装配,销毁等功能
SpringContext:ApplicationContext,扩展核心容器,提供事件处理、国际化等功能。它提供了一些企业级服务的功能,提供了JNDI,EJB,RMI的支持。
2) Spring AOP:提供切面支持
3) Spring DAO:提供事务支持,JDBC,DAO支持
4) Spring ORM:对流行的O/R Mapping封装或支持
5) Spring Web:提供Web应用上下文,对Web开发提供功能上的支持,如请求,表单,异常等。
6) Spring Web MVC:全功能MVC框架,作用等同于Struts。
7)核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
开始写代码了
首先是配置文件
maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
创建User类
package com.weno.bean;
public class User {
private String name;
private Integer age;
private String object;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", object='" + object + '\'' +
'}';
}
}
在resources文件夹下新建springConfig文件
首先先使用一个最简单的:
<?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-->
<!--当Spring框架加载的时候,Spring会自动创建Bean对象,并放入内存-->
<bean id="user" class="com.weno.bean.User">
<!--注入:将属性的值注入到Bean对象中【非必填】-->
<!--其中name对应对应Java中对象的属性,value代表赋值-->
<property name="name" value="小明"/>
<property name="age" value="16" />
<property name="object" value="数学"/>
</bean>
</beans>
测试代码
@Test
public void m1(){
/**
*获取Spring的上下文,当有多个文件时,可以放入一个字符串数组:String[]{"bean1.xml","bean2.xml"}
* 当Spring对象被创建时springConfig也会被创建(反射)
*/
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springConfig.xml");
//将对象进行强制转换
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
现在已经对Spring有了个简单的了解,接下来我们在深入了解下
- Spring的注入之XML注入
- getBean()的使用
- \ 的属性介绍
Spring的注入【XML配置】
- 注入方式
- setter注入
- 构造方法注入
- 注入数据类型
- 值类型注入 【8大基本数据类型】
- 引用类型注入 【将依赖对象注入】
setter注入
-
注入简单值:
简单值的例子在上文已经使用,就不在重复介绍。其中是调用对象的
Set
进行注入。 -
注入引用类型【引入其他Bean】
在setter中使用其他Bean要使用到
ref
属性,假如在上面的例子中,User
还有和address
属性。定义Address类,同时在Use类中添加Address的get和set,重写toString方法
package com.weno.bean; public class Address { private String country; private String province; public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } @Override public String toString() { return "Address{" + "country='" + country + '\'' + ", province='" + province + '\'' + '}'; } }
在Bean的配置文件中
- 引用其他Bean
<!-- 第一种写的方式 --> <bean id="address" class="com.weno.bean.Address"> <property name="country" value="中国"/> <property name="province" value="湖南省"/> </bean> <bean id="userWithAddress" class="com.weno.bean.User"> <property name="name" value="小红"/> <property name="age" value="17" /> <property name="object" value="体育"/> <property name="address" ref="address"/> </bean>
- 使用内部Bean
<bean id="userWithAddress1" class="com.weno.bean.User"> <property name="name" value="小红"/> <property name="age" value="17" /> <property name="object" value="体育"/> <property name="address"> <!-- 内部Bean可以没有ID属性,实际上即使有,也没办法使用,是无法通过id来引用内部Bean的 --> <bean id="address1" class="com.weno.bean.Address"> <property name="country" value="中国"/> <property name="province" value="湖南省"/> </bean> </property> </bean>
构造方法注入
使用构造方法函数注入的前提是Bean必须提供带参数的构造函数。
构建构造方法,但是一定要保留以前的默认构造方法,也就是重新写一个public User(){}
public User(String name, Integer age, String object,Address address) {
this.name = name;
this.age = age;
this.object = object;
this.address = address;
}
配置文件xml,参数名必须和变量名保持一致,同时构造方法构造了多少就要注入多少。
<bean id = "userWithAddress2" class="com.weno.bean.User">
<!-- 基本数据类型使用value,引用类型使用ref -->
<constructor-arg name="address" ref="address"/>
<constructor-arg name="age" value="20"/>
<constructor-arg name="name" value="小亮"/>
<constructor-arg name="object" value="英语"/>
</bean>
<!-- 另外引用的方法是:
1. <constructor-arg index=".." value=".."/>
2. <constructor-arg type="java.lang.String" value=".."/>
3. <constructor-arg value=".."/>
但是不是很推荐使用
-->
getBean()函数的使用
首先先说一下spring上下文的获取
spring上下文的获取
- class获取
//此时springConfig.xml文件放在resources文件夹下
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springConfig.xml");
- file获取
//其中里面填写文件springConfig.xml的绝对路径
ApplicationContext applicationContext = new FileSystemXmlApplicationContext()
当然获取还有很多种方式,这是适合新手的两种方式。
getBean()的四种表达形式
-
getBean(String name)
-
参数
name
表是IOC容器中(xml文件中)已经实例化bean的id
或者name
,但是必须有个要求,就是id或者name必须是唯一的。//要进行强制转型 User user = (User) applicationContext.getBean("userWithAddress2");
-
getBean(Class type)
参数
Class<T> type表示
要加载Bean的类型,如果该类没有继承任何(Object除外)父类和实现接口的话,则要求在IOC容器中必须唯一
。//不需要进行强制转型,因为已经指令类型了 Address address = applicationContext.getBean(Address.class);
-
getBean(String name,Class type)
这个就比较牛逼了,即指令了name,又指明了class,这样的话就不需要进行强制转型了。
//不需要进行强制转型 User user = applicationContext.getBean("userWithAddress2",User.class);
-
getBean(String name,Object[] args)
暂时不说
Bean的属性的基本介绍
-
id
id是Bean的唯一标识名,在整个文档中必须是唯一的。使用时,可以通过id得到配置对象
-
class
创建对象类所在的全路径(包名加类名)
-
name
为id创建一个或者多个别名,对,一个或者多个。多个别名之间使用逗号或则空格分开。
-
abstract(默认为false)
如果将abstract设置为
true
,那么就是将bean设置为抽象bean。同时这个bean不能被实例化。一般是将其做为父类bean,然后让子类去继承。 -
parent
parent相当于Java中的继承,让该bean继承父类元素的值。
<!-- 将Bean定义为抽象bean --> <bean id="userBase" class="com.weno.bean.UserBase" abstract="true"> <property name="name" value="小红"/> <property name="age" value="17" /> <property name="object" value="体育"/> </bean> <!-- 继承抽象Bean --> <bean id="user1" class="com.weno.bean.User" parent="userBase"> <property name="address" ref="address"/> </bean>
当然,在Java文件中,
User
是需要继承UserBase
的。public class User extends UserBase
-
scope:Bean的作用范围
-
singleton:默认值 单例的
只有一个实例对象,即使创建多个对象,这些对象也是同一个对象,地址相同。此外,singleton类型的bean定义,从容器启动,到他第一次被请求而实例化开始,只要容器不销毁或退出,该类型的bean的单一实例就会一直存活。
-
prototype:多例的
容器在接受到该类型的对象的请求
getBean()
的时候,会每次都重新生成一个新的对象给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前对象的引用,请求方需要自己负责当前对象后继生命周期的管理工作,包括该对象的销毁。也就是说,容器每次返回请求方该对象的一个新的实例之后, 就由这个对象“自生自灭”了。 对于那些不能共享使用的对象类型,应该将其定义的scope设为prototype。可以在构造方法中测试对象的创建次数
public UserBase() { System.out.println("开始创建"); }
测试类
@Test
public void m8(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springConfig.xml");User user = applicationContext.getBean("user1",User.class); User user1 = applicationContext.getBean("user1",User.class); User user2 = applicationContext.getBean("user1",User.class); System.out.println(user);
}
结果: ```java 开始创建 开始创建 开始创建 User{address=Address{country='中国', province='湖南省'}} UserBase{name='小红', age=17, object='体育'}
-
-
init-method destory-method
init-method属性是bean的初始方法,在创建好bean后调用该方法。
destory-method属性是bean的销毁方法,在销毁bean之前调用该方法,一般在该方法中释放资源
-
lazy-init(默认为default)
lazy-init只有当scop属性为
singleton
起作用-
lazy-init = "true"
延迟加载,不会在Spring启动时被实例化,只有当第一次向容器通过
getBean
时,才会进行实例化。 -
lazy-init = "false"
启动spring就立即进行实例化。
-
-
depends-on(依赖对象)
这个Bean在初始化的时候依赖的对象,会在这个bean被初始化之前创建。
<bean id="user2" class="com.weno.bean.User" parent="userBase" depends-on="address"/>
Spring的第一天就到这里结束了\(≧▽≦)/啦啦啦
下次就是spring的第二天了