1.Spring概述以及为什么要学习Spring
Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护,交给 Spring 管理AOP 编程的支持Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能声明式事务的支持只需要通过配置就可以完成对事务的管理,而无需手动编程方便程序的测试Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序方便集成各种优秀框架Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持降低 JavaEE API 的使用难度。
2.Spring环境搭建
<1>在ecplise新建项目
<2>导入Spring的jar包
<3>导入日志包
<4>创建一个对象
package com.Bean;
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
<5>书写配置文件
applicationContext.xml,建议放在src目录下,并且导入约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给spring管理 -->
<bean name="user" class="com.bean.User"></bean>
</beans>
<4>代码测试
package junit;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bean.User;
public class Test1 {
@Test
public void test1() {
//1.首先创建容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//2.向容器“要”user对象
User u = (User) applicationContext.getBean("user");
//3.打印user对象
System.out.println(u);
}
}
3.IOC和DI
IOC(Inverse Of Control):反转控制,将创建对象的方式反转,以前对象都由自己维护,包的依赖关系也是自己注入。使用spring后,对象的创建以及依赖关系可以有spring完成创建以及注入。
DI(Dependency Injection):依赖注入,实现IOC思想需要DI支持。
注入方式:set方法,构造方法注入,字段注入(不推荐)。
注入类型:值类型注入:8大基本数据类型
引用类型注入:将对象注入
4.BeanFactory和ApplicationContext
BeanFactory(过时):spring原始接口,实现类功能单一,特点是每次获得对象的时候才会创建对象。
ApplicationContext:每次容器启动时就会创建容器中配置的所有对象,提供更多功能。
-------从类路径加载配置文件:ClassPathXmlApplactionContext("类路径");
-------从硬盘绝对路径加载配置文件:FileSystemXmlApplicationContext("绝对路径");
web开发中,使用applicationContext,在资源匮乏的时候使用BeanFactory。
5.Spring配置
<1>Bean元素
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User对象交给spring管理 -->
<!-- Bean元素:使用该元素需要spring容器管理的对象
name属性:被管理对象的名称,获得对象的时候通过该名称获得。
class属性:被管理对象的完整类名,
可以重复可以使用特殊字符。
id属性:与name属性一模一样,
名称不可重复切不可使用特殊字符。
尽量使用name属性
-->
<bean id="" name="user" class="com.bean.User"></bean>
</beans>
<2>三种对象的创建方式
<!-- 创建方式一:空参构造创建 -->
<bean id="" name="user" class="com.bean.User"></bean>
先在User对象中加入无参构造函数,测试输出
public User() {
System.out.println("User对象空参");
}
@Test
//创建方式一:
public void test1() {
//1.首先创建容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("create/applicationContext.xml");
//2.向容器“要”user对象
User u = (User) applicationContext.getBean("user");
//3.打印user对象
System.out.println(u);
}
输出为:User对象空参
User [name=null, age=0]
即确认对象通过空参构造方法创建
<!-- 创建方式二:静态工厂创建
调用UserFactory的createUser方法创建名为user2的对象,放入容器-->
<bean id="" name="user2" class="create.UserFactory" factory-method="createUser"></bean>
创建工厂类和工厂方法,测试输出
package create;
import com.bean.User;
public class UserFactory {
public static User createUser() {
System.out.println("静态工厂创建User");
return new User();
}
}
@Test
//创建方式二:静态工厂创建
public void test2() {
//1.首先创建容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("create/applicationContext.xml");
//2.向容器“要”user对象
User u = (User) applicationContext.getBean("user2");
//3.打印user对象
System.out.println(u);
}
输出为:静态工厂创建User
User对象空参
User [name=null, age=0]
即确认对象通过静态工厂方法创建
<!-- 创建方式s三:实例工厂创建
调用UserFactory对象的createUser2方法创建名为user3的对象,放入容器-->
<bean id="" name="user3"
factory-bean="userFactory"
factory-method="createUser2"></bean>
<bean name="userFactory" class="create.UserFactory" ></bean>
在UserFactory加入实例工厂方法,测试输出
public User createUser2() {
System.out.println("实例工厂创建User");
return new User();
}
@Test
//创建方式二:动态工厂创建
public void test3() {
//1.首先创建容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("create/applicationContext.xml");
//2.向容器“要”user对象
User u = (User) applicationContext.getBean("user3");
//3.打印user对象
System.out.println(u);
}
输出为:实例工厂创建User
User对象空参
User [name=null, age=0]
即确认对象通过动态工厂方法创建
<3>Bean的scope属性
destroy-method:配置一个方法作为生命周期销毁方法,spring容器在关闭前并销毁所有容器中的对象之前
在配置文件中添加属性
<!-- 创建方式一:空参构造创建 -->
<bean id="" name="user" class="com.bean.User" init-method="init" destroy-method="destroy"></bean>
在User对象中添加方法
public void init() {
System.out.println("init方法");
}
public void destroy() {
System.out.println("destroy方法");
}
调用方法测试
@Test
// 测试生命周期
public void test() {
// 1.首先创建容器对象
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("create/applicationContext.xml");
// 2.向容器“要”user对象
User u = (User) applicationContext.getBean("user");
// 3.关闭容器,触发销毁方法
applicationContext.close();
}
输出为:User对象空参
init方法
静态工厂创建User
User对象空参
实例工厂创建User
User对象空参
destroy方法
<5>spring的模块化配置
<import resource="其他配置文件"/>
导入其他配置文件
<6>spring属性注入
<!-- set方式注入: -->
<bean id="" name="user" class="com.bean.User">
<!-- 为User对象中名为name的属性注入tom为值 -->
<property name="name" value="tom"></property>
<property name="age" value="18"></property>
</bean>
测试输出
@Test
public void test1() {
//1.创建容器对象
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("injection/applicationContext.xml");
//2.获取user对象
User user=(User) applicationContext.getBean("user");
//3.打印user对象
System.out.println(user);
}
输出为:User对象空参
User [name=tom, age=18]
获得的user对象的属性已经被设置好。
(2)引用类型注入
在User中加入对象引用
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
配置文件
<bean id="" name="user" class="com.bean.User">
<!-- 为User对象中名为name的属性注入tom为值 -->
<property name="name" value="tom"></property>
<property name="age" value="18"></property>
<!-- 为car属性诸如下方配置的car对象 -->
<property name="car" ref="car"></property>
</bean>
<!-- 将car对象配置到容器 -->
<bean name="car" class="com.bean.Car">
<property name="name" value="奔驰"></property>
<property name="color" value="red"></property>
</bean>
获得对象并打印对象,得到输出为:User对象空参
User [name=tom, age=18, car=Car [name=奔驰, color=red]]
获得的user对象的属性已设置好
2>构造函数注入:
在User中加入如下构造方法
public User(String name, Car car) {
System.out.println("User(String name,Car car)!!!");
this.name = name;
this.car = car;
}
配置文件,name属性指定参数名
<!-- 构造函数注入 -->
<bean name="user1" class="com.bean.User">
<constructor-arg name="name" value="Jerry"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
</beans>
获得对象并打印对象,输出为;User对象空参
User(String name,Car car)!!!
User [name=Jerry, age=0, car=Car [name=奔驰, color=red]]
再次尝试加入如下构造方法
public User(Car car, String name) {
System.out.println("User(Car car,String name)!!!");
this.name = name;
this.car = car;
}
获得对象并打印对象,输出为:User对象空参
User(Car car,String name)!!!
User [name=Jerry, age=0, car=Car [name=奔驰, color=red]]
可以看出这里使用了新添加的构造方法创建对象。这里可以使用index属性指定参数索引
<!-- 构造函数注入 -->
<bean name="user1" class="com.bean.User">
<constructor-arg name="name" value="Jerry" index="0"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
再加入一种构造函数
public User(Integer name, Car car) {
System.out.println("User(String name,Car car)!!!");
this.name = name+"";
this.car = car;
}
为了能够指定是第一种构造方法,还需要制定第一个参数的类型,使用type属性指定参数类型
<!-- 构造函数注入 -->
<bean name="user1" class="com.bean.User">
<constructor-arg name="name" value="Jerry" index="0" type="java.lang.String"></constructor-arg>
<constructor-arg name="car" ref="car"></constructor-arg>
</bean>
这里表示,
使用第一个参数name名为name且类型为java.lang.String的构造方法
3>p名称空间注入(了解)
4>spel注入(了解)
<7>复杂类型注入
创建一个CollectionBean类
package com.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.sun.xml.internal.fastinfoset.sax.Properties;
public class CollectionBean {
private Object[] arr;//数组类型注入
private List list;//List/set类型注入
private Map map;//Map类型注入
private Properties properties;//properties类型注入
public Object[] getArr() {
return arr;
}
public void setArr(Object[] arr) {
this.arr = arr;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean [arr=" + Arrays.toString(arr) + ", list=" + list + ", map=" + map + ", properties="
+ properties + "]";
}
}
<!-- 复杂类型注入 -->
<bean name="cb" class="com.bean.CollectionBean">
<!-- array类型注入 -->
<!-- 如果数组中只准备注入一个值(对象),直接使用valueref即可 -->
<!-- <property name="arr" value="tom"></property> -->
<property name="arr">
<array>
<value>tom</value>
<value>jerry</value>
<ref bean="user1"/>
</array>
</property>
<!-- List类型注入 -->
<!-- 如果数组中只准备注入一个值(对象),直接使用value|ref即可 -->
<!-- <property name="list" value="jack"></property> -->
<property name="list">
<list>
<value>jack</value>
<value>lucy</value>
<ref bean="user1"/>
</list>
</property>
<!-- Map类型注入 -->
<property name="map">
<map>
<entry key="url" value="jdbc:mysql:///crm"></entry>
<entry key="user" value-ref="user1"></entry>
<entry key-ref="user" value-ref="car"></entry>
</map>
</property>
<!-- properties类型注入 -->
<property name="properties">
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">root</prop>
<prop key="userName">123456</prop>
</props>
</property>