通俗一点来说baen就是java对象,只不过是由容器创建,并且由容器管理对象生命周期。 Bean的本质就是Java中的对象,而Spring中的Bean其实就是对实体类的引用,来生产Java类对象,从而实现生产和管理Bean 。
Bean的配置使用xml配置,XML配置文件的根元素是,中包含了多个子元素,每一个子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。关于元素的常用属性如下表所示: id :bean 再容器的唯一标识 name: bean 在容器中一个标识name ,namek可以有多个使用,或者; 分割 class:bean 创建时要按照那个类类进行创建 注:id必须是Bean中唯一的,而name可以有多个
在Spring中,要想使用容器中的Bean,也需要实例化Bean。实例化Bean有三种方式: 1.构造器实例化 2. 静态工厂方式实例化 3. 实例工厂方式实例化 (其中最常用的是构造器实例化)
容器调用无参构造方法创建对象
可以自定创建的对象,并且将对象交给容器管理实现
创建静态工厂
/** * 静态工厂 */ public class StaticStudentFactory { /** * 自定义 Student 对象的创建 * * // 获取了创建对象的权力 * @return */ public static Student createStudent(){ Student student = new Student(); // 比如name 去网络查询 数据库查询 student.setName("xiaoming"); student.setId(1000); return student; } }声明使用工厂创建的对象,配置xml文件
<?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 像容器声明创建对象 此时创建对象是由静态工厂创建 而不是容器直接创建 class="com.yyf.factory.StaticStudentFactory" 创建对象的静态工厂 factory-method="createStudent" 制定创建对象的静态工厂方法 --> <bean id="student" class="com.yyf.factory.StaticStudentFactory" factory-method="createStudent"> </bean> </beans>测试、获取对象
public class StaticFactoryTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory/staticfactory_bean.xml"); Student student = (Student) applicationContext.getBean("student"); System.out.println("student:"+student); } }作用和静态工厂实例化一致 总结:静态工厂实例化和是工厂实例化 作用是根据自己定义需求创建对象,主要用于dao层连接的初始(解决MySQL密码加密问题、密码的加密解密问题)
在配置文件声明bean 在容器只有一个唯一bean ,当每次获取都是同一个bean singleton 1.在容器启动只创建一个 id 为student 的bean 2.并且放置在容器中,容器管理他的生命周期
当用户向容器获取bean 时,容器才创建,容器只负责创建,不负责保存维护他的生命周期 1.用户向容器获取时 创建id student2对象 2.每次都创建新的对象 3.容器只负责帮我们创建 不会放置在容器中,不会管理bean 的生命周期 , 由用户自己负责
例子: xml文件配置
<?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"> <!-- 声明让容器创建一个 Student类型的bean id student1 scope="singleton" 容器创建bean scope 默认的 作用域是单例singleton singleton 1.在容器启动只创建一个 id 为student1 bean 2.并且放置在容器中,容器管理他的生命周期 --> <bean id="student1" class="com.yyf.entity.Student" scope="singleton"> <property name="id" value="1000"></property> <property name="name" value="xiaoming"></property> </bean> <!-- 声明让容器创建bean 作用域prototype prototype 1.用户向容器获取时 创建id student2对象 2.每次都创建新的对象 3.容器只负责帮我们创建 不会放置在容器中,不会管理bean 的生命周期 ,由用户自己负责 --> <bean id="student2" class="com.yyf.entity.Student" scope="prototype"> </bean> </beans>测试
public class SingletonTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope/singleton_bean.xml"); Student student1_A = (Student) applicationContext.getBean("student1"); System.out.println("student1_A:"+student1_A); Student student1_B = (Student) applicationContext.getBean("student1"); System.out.println("student1_B:"+student1_B); System.out.println("student1_A == student1_B:"+(student1_A == student1_B)); System.out.println("***************************************************"); // 获取 原型的student2 当获取时 容器创建 Student student2_A = (Student) applicationContext.getBean("student2"); System.out.println("student2_A:"+student2_A); // 第二次获取 原型的student2 当获取时 容器创建 Student student2_B = (Student) applicationContext.getBean("student2"); System.out.println("student2_B:"+student2_B); System.out.println("student2_A== student2_B:"+(student2_A==student2_B)); } }bean 的生命周期 单例的bean:随着容器的启动,bean 创建,容器并负责维护bean的生命周期 原型的bean: 容器启动时不创建bean,当用户获取时容器才创建bean,每次都是新的bean,容器部管理他的生命周期
什么是bean的装配
Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配(其中最常用的是基于注解的装配)
1.必有由无参构造 2.必须有setter方法
使用setter方法注入,必备条件:**Bean类必须有一个无参构造方法,Bean类必须为属性提供setter方法 1.必须有构造方法 2.使用<constructor-arg 进行初始化
示例 先附上student实体类
public class Student { private int id; private String name; private List<String> courseList ; public List<String> getCourseList() { return courseList; } public void setCourseList(List<String> courseList) { this.courseList = courseList; } public Student(int id, String name) { this.id = id; this.name = name; } public Student(int id, String name, List<String> courseList) { this.id = id; this.name = name; this.courseList = courseList; } public Student() { System.out.println("student无参构造被调用"); } /** * 初始化方法 */ public void init(){ System.out.println("name:"+name+"Student-init()"); } /** * 销毁方法 */ public void destroy(){ System.out.println("name:"+name+"Student-destroy()"); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", courseList=" + courseList + '}'; } }dao层有一个studentDao接口 有一个方法为findStudentById用于测试
public interface IStudentDao { /** * 更具id 查找student * @param id * @return */ Student findStudentById(int id); }dao.impl层有一个studentDaoImpl实现Dao层接口
@Repository// 标记当前类是dao层 public class IStudentDaoImpl implements IStudentDao { public Student findStudentById(int id) { Student student = new Student(); student.setId(id); student.setName("鞠婧祎"); return student; } }service层 StudentService
public interface StudentService { /** * 更具id 查找student * @param id * @return */ Student findStudentById(int id); }service.impl实现层StudentServiceImpl
//@Component // 将当前类 生成对象并加入到 容器 @Service // 继承 @Component 功能 public class StudentServiceImpl implements StudentService { // 使用注入的注解 注入bean //@Autowired // 去容器中 根据对应类型 查找对应bean ,并设置到当前 属性中 //如果容器有 多个类型的bean则报错 // @Qualifier("studentDao1") // @Qualifier 与@Autowired 配合 ,当根据类型找到多个时 使用 @Qualifier 按照id 或者name 查找为一个bean // @Resource // 首先按照 id 为属性名studentDao 去容器中找到对应的bean 2.如果找不到 在按照类型去查找 如果找到多个 报错 //@Resource(name = "studentDao1") // 如果传递 name 则按照 name 为studentDao1 去容器中查找 id 或者name 相同的bean @Autowired private IStudentDao studentDao ; public IStudentDao getStudentDao() { return studentDao; } public void setStudentDao(IStudentDao studentDao) { this.studentDao = studentDao; } public StudentServiceImpl() { } public StudentServiceImpl(IStudentDao studentDao) { this.studentDao = studentDao; } public Student findStudentById(int id) { return studentDao.findStudentById(id); } }xml配置,1.必须有构造方法 2.使用 进行初始化
<?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"> <!-- 基于xml setter 装配 设置值 必须由两个条件 :1.有无参构造 2.要有setter 方法 必不可少 --> <bean id="student1" class="com.qfedu.entity.Student"> <property name="name" value="xiaoming"></property> <property name="id" value="1000"></property> <property name="courseList" > <list> <value>java</value> <value>c++</value> <value>python</value> </list> </property> </bean> <!-- 基于xml 构造方法的装配 初始化 <constructor-arg 给构造参数 传数据 index="0" 下标0 代表第一个参数 value="1001" 第一个参数的值 --> <bean id="student2" class="com.qfedu.entity.Student"> <constructor-arg index="0" value="1001"></constructor-arg> <constructor-arg index="1" value="xiaohua"></constructor-arg> <constructor-arg index="2"> <list> <value>java</value> <value>c++</value> <value>python</value> </list> </constructor-arg> </bean> <bean id="studentDao" class="com.yyf.dao.impl.IStudentDaoImpl"></bean> <bean id="studentService" class="com.yyf.service.StudentServiceImpl"> <!-- ref="studentDao" 通过ref 引用id studentDao的bean 进行装配 --> <property name="studentDao" ref="studentDao"> </property> </bean> </beans>测试
public class XmlTest { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("xml/settter_bean.xml"); // 按照类型 去获取 Bean 如果容器中只有一个 bean 可以,如果有多个同类型的bean // 则报错 available: expected single matching bean but found 2: student1,student2 // 容器找到了 两个bean ,但是不确定你需要那一个bean // 需要你传更确且 name id 来查找 Student student1 = (Student) applicationContext.getBean("student1"); System.out.println("student1:"+student1); Student student2 = (Student) applicationContext.getBean("student2"); System.out.println("student2:"+student2); // 获取类型 StudentService.class 实例 bean StudentService studentService = applicationContext.getBean(StudentService.class); Student student3 = studentService.findStudentById(2000); System.out.println("student3:"+student3); } }基于XML的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。
@Autowired:去容器中 根据对应类型 查找对应bean ,并设置到当前 属性中 如果容器有 多个类型的bean则报错
@Qualifier(“studentDao1”) : @Qualifier 与@Autowired 配合 ,当根据类型找到多个时 使用 @Qualifier 按照id 或者name 查找为一个bean
@Resource:首先按照 id 为属性名studentDao 去容器中找到对应的bean 2.如果找不到 在按照类型去查找 如果找到多个 报错
@Resource(name = “studentDao1”) 如果传递 name 则按照 name 为studentDao1 去容器中查找 id 或者name 相同的bean
这四个注解都是都一个作用生成bean,@Component是其他三个的父类
@Component
@Repository 指明当前实例 是dao 层的实例
@Service 指明当前实例是service 层的实例
@Controller 指明当前实例是控制 层的实例 但是springmvc 中控制层只能用 @Controller
只能进行注入,使注入的注解生效,bean的生成还需要在xml进行配置*实现是 <context:annotation-config></context:annotation-config>
1.首先在容器中声明bean
2.使用对应注入的注解 注入bean
3.是注入的注解生效
举例 xml文件配置
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 作用就是让 注入的注解生效 --> <context:annotation-config></context:annotation-config> <!--1. 声明 bean--> <bean id="studentDao" class="com.yyf.dao.impl.IStudentDaoImpl"></bean> <bean id="studentService" class="com.yyf.service.StudentServiceImpl"> </bean> </beans>测试
public class StudentServiceImpl implements StudentService { // 使用注入的注解 注入bean @Autowired // 去容器中 根据对应类型 查找对应bean ,并设置到当前 属性中 private IStudentDao studentDao ; public IStudentDao getStudentDao() { return studentDao; } public void setStudentDao(IStudentDao studentDao) { this.studentDao = studentDao; } public Student findStudentById(int id) { return studentDao.findStudentById(id); } }自动注解就是 通过注解自动的生成bean 并经行装配
实现:在xml 声明 context:component-scan 使对应包下的 注入的注解(@Autowired @Qualifie @Resource )生成bean的注解(@Component@Repository @Service @Controller)生效
实现 1.开启自动注解
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 开启 自动注解功能 使 注入的注解(@Autowired @Qualifie @Resource )生成bean的注解(@Component@Repository @Service @Controller)生效 --> <context:component-scan base-package="com.yyf"></context:component-scan> </beans>2.标记需要 生成 bean 和主要注入的属性 dao层
//@Component("studentDao1") // 将IStudentDaoImpl 生成实例 并加入到容器中 为生成的bean 制定id studentDao1 @Repository // 标记当前类是dao层 public class IStudentDaoImpl implements IStudentDao { public Student findStudentById(int id) { Student student = new Student(); student.setId(id); student.setName("xxxx"); return student; } }service层
//@Component // 将当前类 生成对象并加入到 容器 @Service // 继承 @Component 功能 public class StudentServiceImpl implements StudentService { // 使用注入的注解 注入bean // @Autowired // 去容器中 根据对应类型 查找对应bean ,并设置到当前 属性中 //如果容器有 多个类型的bean则报错 // @Qualifier("studentDao1") // @Qualifier 与@Autowired 配合 ,当根据类型找到多个时 使用 @Qualifier 按照id 或者name 查找为一个bean // @Resource // 首先按照 id 为属性名studentDao 去容器中找到对应的bean 2.如果找不到 在按照类型去查找 如果找到多个 报错 @Resource(name = "studentDao1") // 如果传递 name 则按照 name 为studentDao1 去容器中查找 id 或者name 相同的bean private IStudentDao studentDao ; public IStudentDao getStudentDao() { return studentDao; } public void setStudentDao(IStudentDao studentDao) { this.studentDao = studentDao; } public Student findStudentById(int id) { return studentDao.findStudentById(id); } }测试
public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("annotation/auto_bean.xml"); // 获取类型 StudentService.class 实例 bean StudentService studentService = applicationContext.getBean(StudentService.class); Student student3 = studentService.findStudentById(2000); System.out.println("student3:"+student3); }所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。 Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowire属性有5个值.
xml配置
<?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="studentDao" class="com.qfedu.dao.impl.IStudentDaoImpl"></bean> <bean id="studentDao2" class="com.qfedu.dao.impl.IStudentDaoImpl"></bean> <!-- 基于 xml 自动装配 autowire="byType" StudentServiceImpl 中属性 需要那些bean 就去根据类型去容器查找对应bean autowire="byName" StudentServiceImpl 根据属性中对应属性名 作为id 去查找 ,如果找不到就不设置对应的属性 autowire="constructor" 1.首先根据类型去类型 去查找,如果找到一个就设置对应bean 2.如果找到两个 则根据参数变量名去查找 根据构造器中对应 参数名作为id 去查找 查找不到就传null --> <bean id="studentService" class="com.qfedu.service.StudentServiceImpl" autowire="constructor"> </bean> </beans>测试
/** * xml 自动装配 */ public class XMLAuto { public static void main(String[] args) { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("xml/xml_auto_bean.xml"); // 获取类型 StudentService.class 实例 bean StudentService studentService = applicationContext.getBean(StudentService.class); Student student3 = studentService.findStudentById(2000); System.out.println("student3:"+student3); } }