文章目录
IOC简介
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。
Spring提供IOC容器实现两种方式(两个接口):
- BeanFactory:IOC容器基本实现,是spring内部使用的接口,不提供给开发人员使用
- 加载配置文件时,不会主动创建对象,在使用对象时才会创建
- ApplicationContext:BeanFactory的子接口,提供更多更强大的功能,供开发人员使用
- 加载配置文件时, 完成对象创建
- 主要有是个实现类
- ClassPathXmlApplicationContext
- FileSystemApplicationContext
IOC操作之bean管理
什么是bean管理?
bean管理就是两个操作
- 创建对象
- 注入属性
bean管理操作两种方式:
- 基于xml配置文件方式实现
- 基于注解方式实现
基于xml方式装配Bean
在Spring刚出现的时候,XML是描述配置的主要方式,但随着强大的自动化配置和基于Java的配置出现,XML已经不再是第一选择了。
对象创建
在spring配置文件中,使用bean标签,添加对应属性,即可实现对象创建
<bean id="user" class="com.happy.learn.model.User"/>
- id属性:唯一标识
- class属性:要创建的对象全路径
- name属性:可以使用特殊符号,其他同id属性,基本不使用了
如上创建对象时,默认执行无参构造方法。
通过xml方式注入属性
DI:依赖注入,是IOC的一种具体实现,就是注入属性
使用set方法注入
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 +
'}';
}
}
<bean id="user" class="com.happy.learn.model.User">
<property name="age" value="12"/>
<property name="name" value="旺财"/>
</bean>
ClassPathXmlApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
User user = xmlApplicationContext.getBean("user", User.class);
System.out.println(user);
输出结果为:User{name='旺财', age=12}
使用有参构造函数注入
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<bean id="student" class="com.happy.learn.model.Student">
<constructor-arg name="age" value="34"/>
<constructor-arg name="name" value="大强"/>
<!--<constructor-arg index="0" value="34"/>
<constructor-arg index="1" value="大强"/>-->
</bean>
Student student = xmlApplicationContext.getBean("student", Student.class);
System.out.println(student);
输出结果为:Student{name='大强', age=34}
p名称空间注入
简化基于xml配置方式,了解即可
在beans.xml文件中,声明命名空间
<bean id="user2" class="com.happy.learn.model.User" p:age="12" p:name="旺财"/>
注入其他类型属性
字面量
null值
<property name="name" value=""/> User{name='', age=12}
<property name="name">
<null/><!--User{name='null', age=12}-->
</property>
插入特殊符号
a. 符号转义,eg. < >
b. 使用CDATA
<property name="address">
<value><![CDATA[<<北京市>>]]></value>
</property>
输出结果为:User{name='孙大圣', age=12, address='<<北京市>>'}
注入外部bean
a. 创建两个类,service和dao
public interface UserDao {
public void add();
}
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("userDao add....");
}
}
public class UserService {
public void add(){
System.out.println("userService add...");
}
}
b. 在service中,调用dao方法
public class UserService {
// 声明userDao,提供set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("userService add...");
userDao.add();
}
}
c. 在spring配置文件中进行配置
<bean id="userService" class="com.happy.learn.service.UserService">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.happy.learn.dao.UserDaoImpl"/>
注入内部bean
- 一对多 eg. 部门与员工
- 在实体类中表示一对多关系
public class Department {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Department{" +
"name='" + name + '\'' +
'}';
}
}
public class Employee {
private String name;
private String gender;
private Department department;
public void setName(String name) {
this.name = name;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", department=" + department +
'}';
}
}
- 在spring配置文件中进行相关配置
<bean id="employee" class="com.happy.learn.model.Employee">
<property name="name"value="张三"/>
<property name="gender" value="男"/>
<!-- 可以使用内部bean -->
<property name="department">
<bean id="department" class="com.happy.learn.model.Department">
<property name="name" value="研发部"/>
</bean>
</property>
</bean>
输出结果为:Employee{name='张三', gender='男', department=Department{name='研发部'}}
注入内部bean之级联赋值
第一种写法
<bean id="employee" class="com.happy.learn.model.Employee">
<property name="name" value="张三"/>
<property name="gender" value="男"/>
<property name="department" ref="department"/>
</bean>
<bean id="department" class="com.happy.learn.model.Department">
<property name="name" value="研发部"/>
</bean>
第二种写法
添加get方法:
public Department getDepartment() {
return department;
}
<bean id="employee" class="com.happy.learn.model.Employee">
<property name="name" value="张三"/>
<property name="gender" value="男"/>
<property name="department" ref="department"/>
<property name="department.name" value="总裁办"/>
</bean>
<bean id="department" class="com.happy.learn.model.Department">
<property name="name" value="财务部"/>
</bean>
Employee{name='张三', gender='男', department=Department{name='总裁办'}}
通过xml注入集合属性
- 注入数组类型属性
- 注入List集合类型属性
- 注入Map集合类型属性
- 注入Set集合类型属性
public class Teacher {
private String[] course;
private List<String> list;
private Map<String, String> map;
private Set<String> set;
public void setCourse(String[] course) {
this.course = course;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
@Override
public String toString() {
return "Teacher{" +
"course=" + Arrays.toString(course) +
", list=" + list +
", map=" + map +
", set=" + set +
'}';
}
}
<bean id="teacher" class="com.happy.learn.model.Teacher">
<property name="course">
<array>
<value>数学</value>
<value>英语</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<property name="map">
<map>
<entry key="name" value="旺财"/>
<entry key="age" value="12"/>
</map>
</property>
<property name="set">
<set>
<value>篮球</value>
<value>足球</value>
</set>
</property>
</bean>
Teacher{course=[数学, 英语], list=[张三, 李四], map={name=旺财, age=12}, set=[篮球, 足球]}
在集合中设置对象类型的值
private List<Student> students;
public void setStudents(List<Student> students) {
this.students = students;
}
<property name="students">
<list>
<!--注入list集合,但值为对象-->
<ref bean="s1"/>
<ref bean="s2"/>
</list>
</property>
<bean id="s1" class="com.happy.learn.model.Student">
<constructor-arg name="age" value="34"/>
<constructor-arg name="name" value="大强"/>
</bean>
<bean id="s2" class="com.happy.learn.model.Student">
<constructor-arg name="age" value="18"/>
<constructor-arg name="name" value="小明"/>
</bean>
Teacher{course=[数学, 英语], list=[张三, 李四], map={name=旺财, age=12}, set=[篮球, 足球], students=[Student{name='大强', age=34}, Student{name='小明', age=18}]}
把集合注入部分提取
在spring配置文件中引入名称空间util
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
使用util标签完成集合注入提取
<!-- 提取集合类型属性注入 以list为例 -->
<util:list id="courseList">
<value>三国演义</value>
<value>封神榜</value>
<value>红楼梦</value>
<value>西游记</value>
</util:list>
<!-- <property name="list">-->
<!-- <list>-->
<!-- <value>张三</value>-->
<!-- <value>李四</value>-->
<!-- </list>-->
<!-- </property>-->
<property name="list" ref="courseList"/>
XML自动装配
通过autowire
开启自动装配,有两个选项,分别为byName
和byType
,区别如下:
- byName: 按照属性名自动装配
- byType: 根据属性类型自动装配,如果有多个同类型的bean,会报错
<bean id="emp" class="com.happy.learn.model.Employee" autowire="byName"/>
<bean id="department" class="com.happy.learn.model.Department"/>
FactoryBean
在spring
中有两种Bean
,一种是普通Bean
,另外一种就是FactoryBean
。
- 普通Bean:在
spring
配置文件中,定义的类型就是返回的类型 - 工厂Bean:在配置文件中
Bean
类型可以和返回的类型不一样
创建一个类,让这个类作为工厂Bean
,实现FactoryBean
接口
实现接口方法,在方法中定义返回Bean
类型
public class MyFactoryBean implements FactoryBean<Student> {
@Override
public Student getObject() throws Exception {
Student student = new Student("旺财", 12);
return student;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
<bean id="myFactoryBean" class="com.happy.learn.factory.MyFactoryBean"/>
输出结果为:Student{name='旺财', age=12}