一、Spring简介
Spring是一个项目管理框架,同时也是一套Java EE解决方案。
Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。
Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"。
二、创建Maven工程项目
1.点击创建新project
2.选择Maven工程
3.修改GAV坐标
然后就可以开始搭建spring环境了
4.在pom.xml文件中引入spring-context依赖
5.在java目录下的resources文件夹下创建spring的配置文件 名字随意 但一般都约定俗成的取为“applicationContext.xml” 这样一看就会知道这个配置文件是spring的配置文件
<?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>
这样spring环境就搭建好了,其实spring框架有很多模块,而这些模块使用的jar包有不尽相同,在这些jar包之间有相互有着联系:
但我们可以不用管这些关系 ,因为在引入spring-context这个jar包依赖的时候Maven框架就已经自动的帮我们把这些依赖都一起下载了。
三、Spring通过xml配置文件注册bean的方法 或者是IOC控制反转
1.向spring容器注册bean(无参数传递)
用一个dao层与service层的例子
UserDao
package com.qfedu.demo.dao;
public class UserDao {
public String sayHello(){
return "hello";
}
}
spring配置文件
<!--向 Spring 容器注册一个 Bean-->
<!-- 这个name就是将来获取UserDao对象的对象名 class就是UserDao实例化的路径 基于反射原理实现-->
<bean name="userDao" class="com.qfedu.demo.dao.UserDao"/>
<!-- 这种方法获取的对象 都是通过反射调用该类的无参构造实例化而来的 是不携带参数的-->
<bean name="userDao2" class="com.qfedu.demo.dao.UserDao"/>
测试:
public class Demo1 {
public static void main(String[] args) {
//默认会去 classpath 下查找配置文件
//初始化 Spring 容器,默认情况下,当容器初始化的时候,UserDao 就已经被实例化了
//这行代码的作用就是读取 xml 中的 class 属性,利用反射创建出来一个 Bean
ClassPathXmlApplicationContext cpac = new ClassPathXmlApplicationContext("applicationContext.xml");
//跟 Spring 容器去要一个名为 userDao 的 Bean
//这种方法要注意的是 name的名字不能写错 要对应xml中的name 如果写错就会出现异常错误 NoSuchBeanDefinitionException
UserDao userDao = (UserDao) cpac.getBean("userDao");
System.out.println(userDao.sayHello());
//通过这种方式想Spring容器要对象的时候 明确告诉Spring容器 要的是一个UserDao对象
UserDao u3 = cpac.getBean("userDao2", UserDao.class);
System.out.println("u3.sayHello() = " + u3.sayHello());
/*//这种方式获取要注意的是 如果在xml文件中配置有多个UserDao的bean就出现异常错误 NoUniqueBeanDefinitionException
//如果使用这种方式 就要确保Spring容器中只有一个对应类的Bean
UserDao u2 = cpac.getBean(UserDao.class);
System.out.println("u2.sayHello() = " + u2.sayHello());*/
}
}
2.向 spring容器注册bean 时并告诉对象的属性是什么(有参数 基本数据类型)
想通过构造方法设置属性使用的是 constructor-arg 标签
想通过set方法设置属性使用的是 property 标签
p 名称空间注入 本质也是set方法设置的
User
package com.qfedu.demo.entity;
public class User {
private Integer id;
private String userName;
private String address;
public User() {
}
public User(Integer id, String userName) {
this.id = id;
this.userName = userName;
}
public User(Integer id, String userName, String address) {
this.id = id;
this.userName = userName;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", address='" + address + '\'' +
'}';
}
}
spring配置文件
<!-- 要是想在向Spring容器里注册bean的时候 同时要告诉Spring 对象的属性是什么 用以下的方法-->
<bean name="u3" class="com.qfedu.demo.entity.User">
<!-- 通过constructor-arg 标签配置的参数就是通过有参的构造方法来实例的对象 如果想只配置其中某几个参数值就得有相对应的构造
方法或者通过set方法进行配置-->
<constructor-arg name="id" value="1001" />
<constructor-arg name="address" value="guangzhou"/>
<constructor-arg name="userName" value="zhangsan"/>
</bean>
<!-- 这是两个参数的-->
<bean name="u4" class="com.qfedu.demo.entity.User">
<!-- Spring容器会自动匹配自有两个参数的构造方法进行调用-->
<constructor-arg name="id" value="1002" />
<constructor-arg name="userName" value="wangwu"/>
</bean>
<!-- 下面是通过set方法进行设置参数值的-->
<bean name="u5" class="com.qfedu.demo.entity.User">
<!-- 通过property标签来获取set方法来给对象赋值 注意的是Spring容器是根据name的值来推断响应的set方法的 get也一样-->
<property name="id" value="1003"/>
<property name="address" value="shenzhen"/>
<property name="userName" value="lisi"/>
</bean>
<!-- p 名称空间注入 本质也是set方法设置的-->
<bean name="u6" class="com.qfedu.demo.entity.User" p:id="1004" p:address="shanghai" p:userName="zhaoliu"/>
<!-- bean标签中的 id与name的区别 id可以设置多个都可以识别 但name设置多个的时候只能识别第一个-->
<!-- <bean id="u1,u2,u3"/>
<bean name="u1,u2,u3"/>
像这种id时 u1,u2,u3 都是可以获取到该bean的 但这种name 只有在name为 (u1,u2,u3) 时 才能获取到这个bean
但这种区别一般用不到 一般也不会这样设置
-->
测试:
User u31 = cpac.getBean("u3", User.class);
User u4 = cpac.getBean("u4", User.class);
User u5 = cpac.getBean("u5", User.class);
User u6 = cpac.getBean("u6", User.class);
System.out.println("(u31+u4+u5+u6) = " + u31 + u4 + u5 + u6);
Person p = cpac.getBean("p", Person.class);
System.out.println("p = " + p);
3.向 spring容器注册bean 时并告诉对象的属性是什么(有参数 对象数据类型或者复杂数据类型)
Person
package com.qfedu.demo.entity;
import java.util.*;
public class Person {
private String name;
private Cat cat;
private List<String> favorites;
private Date birthday;
private Map<String,Object> info;
private Properties info2;
private Dog[] dogs;
public Person() {
}
public Person(String name, Cat cat, List<String> favorites, Date birthday, Map<String, Object> info, Properties info2, Dog[] dogs) {
this.name = name;
this.cat = cat;
this.favorites = favorites;
this.birthday = birthday;
this.info = info;
this.info2 = info2;
this.dogs = dogs;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public List<String> getFavorites() {
return favorites;
}
public void setFavorites(List<String> favorites) {
this.favorites = favorites;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Map<String, Object> getInfo() {
return info;
}
public void setInfo(Map<String, Object> info) {
this.info = info;
}
public Properties getInfo2() {
return info2;
}
public void setInfo2(Properties info2) {
this.info2 = info2;
}
public Dog[] getDogs() {
return dogs;
}
public void setDogs(Dog[] dogs) {
this.dogs = dogs;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", cat=" + cat +
", favorites=" + favorites +
", birthday=" + birthday +
", info=" + info +
", info2=" + info2 +
", dogs=" + Arrays.toString(dogs) +
'}';
}
}
Cat
package com.qfedu.demo.entity;
public class Cat {
private String name;
private Integer age;
private String color;
public Cat() {
}
public Cat(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
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 getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
Dog
package com.qfedu.demo.entity;
public class Dog {
private String name;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
spring配置文件
<!-- 以上都是在向Spring容器注入bean时同时设置的基本数据类型的情况 那如果想设置 集合 数组 对象这种情况该怎么写呢 下面介绍-->
<!-- 在这里实例化一个cat的对象 提供外部引用-->
<bean name="cat" class="com.qfedu.demo.entity.Cat">
<property name="name" value="小京"/>
<property name="age" value="2"/>
<property name="color" value="黄色"/>
</bean>
<bean name="dog" class="com.qfedu.demo.entity.Dog">
<property name="name" value="黑福"/>
</bean>
<bean name="p" class="com.qfedu.demo.entity.Person">
<!-- String类型-->
<property name="name" value="liangnan"/>
<!-- 对象类型 使用引用变量方法来赋值-->
<property name="cat" ref="cat"/>
<!-- list集合类型 -->
<property name="favorites">
<list>
<value>洗脚</value>
<value>按摩</value>
<value>蹦迪</value>
</list>
</property>
<!-- 数组类型 -->
<property name="dogs">
<array>
<!-- 使用外部变量引用-->
<ref bean="dog"/>
<!-- 现new一个变量-->
<bean class="com.qfedu.demo.entity.Dog">
<property name="name" value="小黄"/>
</bean>
</array>
</property>
<!-- map集合类型-->
<property name="info">
<map>
<entry key="age" value="99"/>
<entry key="cat" value-ref="cat"/>
</map>
</property>
<!-- properties类型-->
<property name="info2">
<props>
<prop key="age">99</prop>
<prop key="gender">男</prop>
</props>
</property>
<!-- data类型 固定格式-->
<property name="birthday" value="2003/11/2"/>
</bean>
测试:
package com.qfedu.demo;
import com.qfedu.demo.entity.Person;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo2 {
private ClassPathXmlApplicationContext ctx;
@Test
public void test() {
Person p = ctx.getBean("p", Person.class);
System.out.println("p = " + p);
}
@Before
public void before(){
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@After
public void after(){
ctx.close();
}
}
静态工厂注入,静态工厂注入的意思就是 工厂的方法是静态的,bean标签里的class传递的是静态工厂类的全路径,然后通过bean标签中的factory-method方法掉用这个静态的方法,这个静态方法的返回值最终会被注册到spring容器里面。
实例工厂注入,实例工厂和静态工厂的区别就是 方法不是静态的 ,所以需要先实例化一个工厂对象才能调用方法获取想要的返回值对象 所以要注入两个bean
以上就是spring通过xml文件进行注入的常用方式