文章目录
1. Bean管理概念
Bean管理指的是两个操作,一个是使用Spring创建对象,一个是使用Spring注入属性
- 在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
- 在 bean 标签有很多属性,介绍常用的属性,id 属性:唯一标识, class 属性:类全路径(包类路径)
- 创建对象时候,默认也是执行无参数构造方法完成对象创建(如果类中显示创建了有参构造函数但是没有显示提供无参构造函数,IOC容器创建对象时会报错)
2. 使用set方式注入属性(xml方式)
package cn.edu.xd.dao;
public class User {
String name;
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<?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 id="user" class="cn.edu.xd.dao.User">
<property name="name" value="tom"/>
<property name="age" value="18"/>
</bean>
</beans>
@Test
public void test1(){
System.out.println("get user by IOC");
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");//加载文件
User user=context.getBean("user", User.class);
System.out.println(user);
}
<property name="name" value="tom"/>
name表示属性名称,value表示属性的值
使用p名称空间简化
注入null值
注入特殊字符值
注入外部bean
UserService中的add方法中需要调用UserDao类中的add方法
public class UserService {
UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("UserService add...");
userDao.add();
}
}
public class UserDao {
public void add(){
System.out.println("UserDao add...");
}
}
<bean id="userDao" class="cn.edu.xd.dao.UserDao"/>
<bean id="userService" class="cn.edu.xd.service.UserService">
<property name="userDao" ref="userDao"/>
</bean>
注入内部bean
部门和员工是一对多的关系,一个员工属于某一个部门
public class Dept {
String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
public class Emp {
String name;
int age;
Dept dept;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", age=" + age +
", dept=" + dept +
'}';
}
}
<bean id="emp" class="cn.edu.xd.bean.Emp">
<property name="name" value="tom"/>
<property name="age" value="25"/>
<property name="dept">
<bean id="dept" class="cn.edu.xd.bean.Dept">
<property name="name" value="财政部"/>
</bean>
</property>
</bean>
注入数组和集合类型
package cn.edu.xd.bean;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
String[] courses;//数组类型属性
List<String> list;//list类型属性
Map<String,String> map;//map类型属性
Set<String> set;//set类型属性
public void setCourses(String[] courses) {
this.courses = courses;
}
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 "Student{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", map=" + map +
", set=" + set +
'}';
}
}
<bean id="student" class="cn.edu.xd.bean.Student">
<property name="courses">
<array>
<value>Java</value>
<value>Math</value>
<value>Algorithm</value>
</array>
</property>
<property name="list">
<list>
<value>篮球</value>
<value>排球</value>
<value>羽毛球</value>
</list>
</property>
<property name="map">
<map>
<entry key="JAVA" value="java"/>
<entry key="PHP" value="php"/>
</map>
</property>
<property name="set">
<set>
<value>aa</value>
<value>aa</value>
<value>bb</value>
</set>
</property>
</bean>
注入集合类型,集合元素是对象
public class Student {
List<Course> courses;
public void setCourses(List<Course> courses) {
this.courses = courses;
}
@Override
public String toString() {
return "Student{" +
"courses=" + courses +
'}';
}
}
public class Course {
String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
'}';
}
}
<bean id="student" class="cn.edu.xd.bean.Student">
<property name="courses">
<list>
<ref bean="course1"/>
<ref bean="course2"/>
<ref bean="course3"/>
</list>
</property>
</bean>
<bean id="course1" class="cn.edu.xd.bean.Course" p:name="Java"/>
<bean id="course2" class="cn.edu.xd.bean.Course" p:name="Go"/>
<bean id="course3" class="cn.edu.xd.bean.Course" p:name="C++"/>
注入集合类型,集合元素提取出来
<?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">
<bean id="student" class="cn.edu.xd.bean.Student">
<property name="courses" ref="courseList"/>
</bean>
<util:list id="courseList">
<ref bean="course1"/>
<ref bean="course2"/>
<ref bean="course3"/>
<!-- 如果是普通类型用<value>值</value>-->
</util:list>
<bean id="course1" class="cn.edu.xd.bean.Course" p:name="Java"/>
<bean id="course2" class="cn.edu.xd.bean.Course" p:name="Go"/>
<bean id="course3" class="cn.edu.xd.bean.Course" p:name="C++"/>
</beans>
3. 使用有参构造函数注入(xml方式)
package cn.edu.xd.dao;
public class User {
String name;
int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
<bean id="user" class="cn.edu.xd.dao.User">
<constructor-arg name="name" value="bob"/>
<constructor-arg name="age" value="18"/>
</bean>
4. 工厂bean
Spring中有两种bean, 一种是前面一直使用的普通bean, bean的类型和class中的类型一致,但是工厂bean中的class中的类和实际的bean类型不一致
public class MyBean implements FactoryBean<Course> {
public Course getObject() throws Exception {
Course course = new Course();
course.setName("Java");
return course;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() {
return false;
}
}
public class Course {
String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
'}';
}
}
<bean id="myBean" class="cn.edu.xd.bean.MyBean"/>
可以看出虽然bean.xml中配置的class指向的类是MyBean, 但是返回的实际bean类型是Course
5. bean作用域
在Spring中可以设置bean是单实例还是多实例,默认情况是单实例
<bean id="course" class="cn.edu.xd.bean.Course" p:name="Java"/>
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");//加载文件
Course course1=context.getBean("course",Course.class);
Course course2=context.getBean("course",Course.class);
System.out.println(course1==course2);//true
}
打印结果为true,说明两次获取到的对象相同
设置为多实例
设置为singleton时加载bean.xml文件时就创建了bean对象,设置为prototype时加载bean.xml文件时就不创建bean对象,获取时才创建对象
<bean id="course" class="cn.edu.xd.bean.Course" p:name="Java" scope="prototype"/>
@Test
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");//加载文件
Course course1=context.getBean("course",Course.class);
Course course2=context.getBean("course",Course.class);
System.out.println(course1==course2);//false
}
6. bean生命周期
- 通过构造器创建 bean 实例(无参数构造)
- 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
- 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- 把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
- bean 可以使用了(对象获取到了)
- 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
代码示例:
创建一个后置处理器类:
public class MyBeanPost implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在init函数之前执行");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在init函数之后执行");
return bean;
}
}
xml中配置该类:
<bean id="myBeanPost" class="cn.edu.xd.bean.MyBeanPost"/>
public class Course {
String name;
public Course() {
System.out.println("第一步 执行无参构造方法");
}
public void setName(String name) {
System.out.println("第二步 执行set方法");
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
'}';
}
public void initMethod(){
System.out.println("第三步 执行init方法");
}
public void destroyMethod(){
System.out.println("第五步 执行destroy方法");
}
@Test
public void test1(){
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");//加载文件
Course course1=context.getBean("course",Course.class);
System.out.println("第四步 获取bean实例对象");
System.out.println(course1);
context.close();
}
7. bean自动装配
1. byName
<bean id="student" class="cn.edu.xd.bean.Student" autowire="byName"/>
<!-- course和Student类中的course名称一样,不一样会装配失败-->
<bean id="course" class="cn.edu.xd.bean.Course" p:name="Java"/>
2. byType
<bean id="student" class="cn.edu.xd.bean.Student" autowire="byType"/>
<!-- course和Student类中的course名称不需要一样-->
<bean id="course100" class="cn.edu.xd.bean.Course" p:name="Java"/>
注意一点,采用byType方式时,只能有一个Couser类型的bean, 比如下面这种情况就会报错
8. 使用外部属性文件注入
-
创建一个.properties文件
-
导入context名称空间
-
使用