Spring3-IoC1-IoC容器、基于xml管理bean

目录

IoC容器

概述

依赖注入

IoC容器在Spring中的实现

基于xml管理bean

获取bean

依赖注入

setter注入

构造器注入

特殊值处理

字面量赋值

null值

xml实体

CDATA节

特殊类型属性注入

对象类型属性注入

方式一:引用外部bean

方式二:内部bean

方式三:级联属性赋值

数组类型属性注入

集合类型属性注入

list、set集合类型

map集合类型

引用集合类型 

p命名空间

引入外部属性文件

bean的作用域

bean的生命周期

FactoryBean

基于xml自动装配


IoC容器

概述

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序

Spring 通过 IoC 容器管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别

控制反转是一种思想

控制反转是为了降低程序耦合度,提高程序扩展力

控制反转,反转的是什么?

  • 将对象的创建权利交出去,交给第三方容器负责
  • 将对象和对象之间关系的维护权交出去,交给第三方容器负责

控制反转这种思想如何实现呢?

  • DI(Dependency Injection):依赖注入  

依赖注入

DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想

依赖注入:Spring创建对象的过程中,将对象依赖属性通过配置进行注入

依赖注入常见的实现方式包括两种:

  • set注入
  • 构造注入

Bean管理:Bean对象的创建以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)

IoC容器在Spring中的实现

Spring 的 IoC 容器就是 IoC思想的一个落地的产品实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:

①BeanFactory

这是 IoC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用

②ApplicationContext

BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用ApplicationContext,而不是底层的 BeanFactory

ApplicationContext的主要实现类:

类型名简介
ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力
WebApplicationContext专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中

基于xml管理bean

依赖放入父模块

创建新模块spring-ioc-xml

package com.qcby.spring;public class User {private String name;private Integer age;public void run(){System.out.println("run...");}
}

获取bean

①方式一:根据id获取

由于 id 属性指定了 bean 的唯一标识,所以根据 bean 标签的 id 属性可以精确获取到一个组件对象(入门案例)

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"><!--user对象创建--><bean id="user" class="com.qcby.spring.User"></bean>
</beans>

测试类: 

package com.qcby.spring;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");//根据id获取beanUser user = (User) context.getBean("user");System.out.println("根据id获取bean:"+user);}
}

②方式二:根据类型获取

package com.qcby.spring;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");//根据id获取bean
//        User user = (User) context.getBean("user");
//        System.out.println("根据id获取bean:"+user);//根据类型获取beanUser user = context.getBean(User.class);System.out.println("根据类型获取bean"+user);}
}

当根据类型获取bean时,要求IOC容器中指定类型的bean有且只能有一个 

若配置多个,会抛出异常:org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type

③方式三:根据id和类型

package com.qcby.spring;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");//根据id获取bean
//        User user = (User) context.getBean("user");
//        System.out.println("根据id获取bean:"+user);//根据类型获取bean
//        User user = context.getBean(User.class);
//        System.out.println("根据类型获取bean"+user);//根据id和类型获取beanUser user = context.getBean("user", User.class);System.out.println("根据id和类型获取bean:"+user);}
}

扩展:

如果组件类实现了接口,根据接口类型可以获取 bean 吗?

  • 可以,前提是bean唯一
package com.qcby.spring;public interface UserDao {public void run();
}
package com.qcby.spring;public class UserDaoImpl implements UserDao{@Overridepublic void run() {System.out.println("run...");}
}
 <!--一个接口获取类过程--><bean id="userDaoImpl" class="com.qcby.spring.bean.UserDaoImpl.UserDaoImpl"></bean>
package com.qcby.spring;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUserDao {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");//根据类型获取接口对应beanUserDao userDao = context.getBean(UserDao.class);System.out.println(userDao);userDao.run();}
}

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?

  • 不行,因为bean不唯一

依赖注入

setter注入

第一步:创建类,生成属性set方法

第二步:在spring配置文件配置

package com.qcby.spring.di;public class Book {private String bname;private String author;//无参构造public Book() {}//有参构造public Book(String bname, String author) {this.bname = bname;this.author = author;}//生成get和set方法public void setBname(String bname) {this.bname = bname;}public void setAuthor(String author) {this.author = author;}public String getBname() {return bname;}public String getAuthor() {return author;}@Overridepublic String toString() {return "Book{" +"bname='" + bname + '\'' +", author='" + author + '\'' +'}';}
}
<?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:cache="http://www.springframework.org/schema/cache"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"><!--set方法注入--><!-- property标签:通过组件类的setXxx()方法给组件对象设置属性 --><!-- name属性:指定属性名(这个属性名是getXxx()、setXxx()方法定义的,和成员变量无关) --><!-- value属性:指定属性值 --><bean id="book" class="com.qcby.spring.di.Book"><property name="bname" value="前端开发"></property><property name="author" value="张三"></property></bean>
</beans>
package com.qcby.spring;import com.qcby.spring.di.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestBook {@Testpublic void testSetter(){ApplicationContext context = new ClassPathXmlApplicationContext("bean_di.xml");Book book = context.getBean("book", Book.class);System.out.println(book);}}

构造器注入

第一步:创建类,定义属性,生成有参构造方法

第二步:在spring配置文件配置

    <!--构造器注入--><bean id="bookCon" class="com.qcby.spring.di.Book"><constructor-arg name="bname" value="java开发"></constructor-arg><constructor-arg name="author" value="李四"></constructor-arg></bean>

注意:

constructor-arg标签还有两个属性可以进一步描述构造器参数:

  • index属性:指定参数所在位置的索引(从0开始)
  • name属性:指定参数名
    @Testpublic void testCon(){ApplicationContext context = new ClassPathXmlApplicationContext("bean_di.xml");Book book = context.getBean("bookCon", Book.class);System.out.println(book);}

特殊值处理

字面量赋值

什么是字面量?

int a = 10;

声明一个变量a,初始化为10,此时a不代表字母a,而是作为一个变量的名字。当引用a的时候,实际上拿到的值是10。

而如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身

<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>

null值

<property name="name"><null />
</property>

注意:以下写法为name所赋的值是字符串null

<property name="name" value="null"></property>

xml实体

<!-- 小于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression" value="a &lt; b"/>

CDATA节

<property name="expression"><!-- 解决方案二:使用CDATA节 --><!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 --><!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 --><!-- 所以CDATA节中写什么符号都随意 --><value><![CDATA[a < b]]></value>
</property>

特殊类型属性注入

对象类型属性注入

package com.qcby.spring.ditest;//部门类
public class Dept {private String dname;public void info(){System.out.println("部门名称:"+dname);}public void setDname(String dname) {this.dname = dname;}public String getDname() {return dname;}
}
package com.qcby.spring.ditest;//员工类
public class Emp {//对象类型属性:员工属于某个部门private Dept dept;private String ename;private Integer age;public void work(){System.out.println(ename+"emp work..."+age);dept.info();}public Dept getDept() {return dept;}public void setDept(Dept dept) {this.dept = dept;}public String getEname() {return ename;}public void setEname(String ename) {this.ename = ename;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}
方式一:引用外部bean

使用ref属性

    <!--方式一:引入外部bean1.创建两个类对象:dept emp2.在emp的bean标签里,使用property引入dept的bean--><bean id="dept" class="com.qcby.spring.ditest.Dept"><property name="dname" value="安保部"></property></bean><bean id="emp" class="com.qcby.spring.ditest.Emp"><!--普通属性注入--><property name="ename" value="lucy"></property><property name="age" value="50"></property><!--对象属性注入ref属性:引用IOC容器中某个bean的id,将所对应的bean为属性赋值--><property name="dept" ref="dept"></property></bean>

方式二:内部bean
    <!--方式二:内部bean--><!-- 在一个bean中再声明一个bean就是内部bean --><!-- 内部bean只能用于给属性赋值,不能在外部通过IOC容器获取,因此可以省略id属性 --><bean id="emp2" class="com.qcby.spring.ditest.Emp"><!--普通属性注入--><property name="ename" value="mary"></property><property name="age" value="20"></property><!--对象属性注入--><property name="dept"><bean id="dept2" class="com.qcby.spring.ditest.Dept"><property name="dname" value="财务部"></property></bean></property></bean>

方式三:级联属性赋值
    <!--方式三:级联赋值--><bean id="dept3" class="com.qcby.spring.ditest.Dept"><property name="dname" value="研发部"></property></bean><bean id="emp3" class="com.qcby.spring.ditest.Emp"><!--普通属性注入--><property name="ename" value="tom"></property><property name="age" value="30"></property><!--对象属性注入--><property name="dept" ref="dept3"></property><property name="dept.dname" value="测试部"></property></bean>

数组类型属性注入

员工类:

    //爱好private String[] loves;public String[] getLoves() {return loves;}public void setLoves(String[] loves) {this.loves = loves;}public void work(){System.out.println(ename+"emp work..."+age);dept.info();System.out.println(Arrays.toString(loves));}
        <!--数组类型属性--><property name="loves"><array><value>吃饭</value><value>睡觉</value><value>看电影</value></array></property>

完整的配置文件:

<?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="dept" class="com.qcby.spring.ditest.Dept"><property name="dname" value="技术部"></property></bean><bean id="emp" class="com.qcby.spring.ditest.Emp"><!--普通属性--><property name="ename" value="lucy"></property><property name="age" value="20"></property><!--对象类型属性--><property name="dept" ref="dept"></property><!--数组类型属性--><property name="loves"><array><value>吃饭</value><value>睡觉</value><value>看电影</value></array></property></bean>
</beans>

集合类型属性注入

list、set集合类型

Dept类:

private List<Emp> empList;public void info(){System.out.println("部门名称:"+dname);for (Emp emp : empList) {System.out.println(emp.getEname());}}public List<Emp> getEmpList() {return empList;}public void setEmpList(List<Emp> empList) {this.empList = empList;}}
<?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="empone" class="com.qcby.spring.ditest.Emp"><property name="ename" value="lucy"></property><property name="age" value="20"></property></bean><bean id="emptwo" class="com.qcby.spring.ditest.Emp"><property name="ename" value="mary"></property><property name="age" value="30"></property></bean><bean id="dept" class="com.qcby.spring.ditest.Dept"><property name="dname" value="技术部"></property><property name="empList"><list><ref bean="empone"></ref><ref bean="emptwo"></ref></list></property></bean></beans>

若为Set集合类型属性赋值,只需要将其中的list标签改为set标签即可  

map集合类型

Student和Teacher类:

package com.qcby.spring.dimap;import java.util.Map;public class Student {private Map<String,Teacher> teacherMap;private String sid;private String sname;public void run(){System.out.println("学生编号:"+sid+"学生名称:"+sname);System.out.println(teacherMap);}public Map<String, Teacher> getTeacherMap() {return teacherMap;}public void setTeacherMap(Map<String, Teacher> teacherMap) {this.teacherMap = teacherMap;}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}
}
package com.qcby.spring.dimap;public class Teacher {private String teacherId;private String teacherName;public String getTeacherId() {return teacherId;}public void setTeacherId(String teacherId) {this.teacherId = teacherId;}public String getTeacherName() {return teacherName;}public void setTeacherName(String teacherName) {this.teacherName = teacherName;}@Overridepublic String toString() {return "Teacher{" +"teacherId='" + teacherId + '\'' +", teacherName='" + teacherName + '\'' +'}';}
}
<?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"><!--1.创建两个对象2.注入普通类型属性3.在学生bean注入map集合类型属性--><bean id="teacherone" class="com.qcby.spring.dimap.Teacher"><!--注入普通类型属性--><property name="teacherId" value="100"></property><property name="teacherName" value="讲师1"></property></bean><bean id="teachertwo" class="com.qcby.spring.dimap.Teacher"><!--注入普通类型属性--><property name="teacherId" value="200"></property><property name="teacherName" value="讲师2"></property></bean><bean id="student" class="com.qcby.spring.dimap.Student"><!--注入普通类型属性--><property name="sid" value="2000"></property><property name="sname" value="李四"></property><!--在学生bean注入map集合类型属性--><property name="teacherMap"><map><entry><!--key--><key><value>1</value></key><!--value为对象--><ref bean="teacherone"></ref></entry><entry><!--key--><key><value>2</value></key><!--value为对象--><ref bean="teachertwo"></ref></entry></map></property></bean></beans>

引用集合类型 

Lesson类:

package com.qcby.spring.dimap;public class Lesson {private String lessonName;public String getLessonName() {return lessonName;}public void setLessonName(String lessonName) {this.lessonName = lessonName;}@Overridepublic String toString() {return "Lesson{" +"lessonName='" + lessonName + '\'' +'}';}
}
package com.qcby.spring.dimap;import java.util.List;
import java.util.Map;public class Student {private List<Lesson> lessonList;private Map<String,Teacher> teacherMap;private String sid;private String sname;public void run(){System.out.println("学生编号:"+sid+"学生名称:"+sname);System.out.println(teacherMap);System.out.println(lessonList);}public List<Lesson> getLessonList() {return lessonList;}public void setLessonList(List<Lesson> lessonList) {this.lessonList = lessonList;}public Map<String, Teacher> getTeacherMap() {return teacherMap;}public void setTeacherMap(Map<String, Teacher> teacherMap) {this.teacherMap = teacherMap;}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}
}

使用util:list、util:map标签必须引入相应的命名空间  

<?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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--1.创建三个对象2.注入普通类型属性3.使用util:类型定义4.在学生bean引入util:类型定义bean,完成list、map类型属性注入--><bean id="lessonone" class="com.qcby.spring.dimap.Lesson"><property name="lessonName" value="java"></property></bean><bean id="lessontwo" class="com.qcby.spring.dimap.Lesson"><property name="lessonName" value="python"></property></bean><bean id="teacherone" class="com.qcby.spring.dimap.Teacher"><property name="teacherId" value="100"></property><property name="teacherName" value="讲师1"></property></bean><bean id="teachertwo" class="com.qcby.spring.dimap.Teacher"><property name="teacherId" value="200"></property><property name="teacherName" value="讲师2"></property></bean><bean id="student" class="com.qcby.spring.dimap.Student"><property name="sid" value="001"></property><property name="sname" value="lucy"></property><!--注入list、map类型属性--><property name="lessonList" ref="lessonList"></property><property name="teacherMap" ref="teacherMap"></property></bean><util:list id="lessonList"><ref bean="lessonone"></ref><ref bean="lessontwo"></ref></util:list><util:map id="teacherMap"><entry><key><value>1001</value></key><ref bean="teacherone"></ref></entry><entry><key><value>1002</value></key><ref bean="teachertwo"></ref></entry></util:map>
</beans>

p命名空间

引入p命名空间:

<?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:util="http://www.springframework.org/schema/util"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">

引入p命名空间后,可以通过以下方式为bean的各个属性赋值:

<bean id="studentSix" class="com.qcby.spring6.bean.Student"p:id="1006" p:name="小明" p:clazz-ref="clazzOne" p:teacherMap-ref="teacherMap"></bean>

引入外部属性文件

1.加入依赖

<!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency><!-- 数据源 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.15</version>
</dependency>

2.创建外部属性文件

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

3.配置bean

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--引入外部属性文件--><context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder><!--完成数据库信息注入--><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean>
</beans>

4.测试

package com.qcby.spring;import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestJdbc {@Testpublic void demo(){ApplicationContext context = new ClassPathXmlApplicationContext("bean_jdbc.xml");DruidDataSource dataSource = context.getBean(DruidDataSource.class);System.out.println(dataSource.getUrl());}
}

bean的作用域

在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义参加下表:

取值含义创建对象的时机
singleton(默认)在IOC容器中,这个bean的对象始终为单实例IOC容器初始化时
prototype这个bean在IOC容器中有多个实例获取bean时

如果是在WebApplicationContext环境下还会有另外几个作用域(但不常用):

取值含义
request在一个请求范围内有效
session在一个会话范围内有效

演示:

1.创建Orders类

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"><!--通过scope属性配置单实例、多实例--><bean id="orders" class="com.qcby.spring.scope.Orders"scope="singleton"></bean>
</beans>
package com.qcby.spring;import com.qcby.spring.scope.Orders;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestOrders {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("bean_scope.xml");Orders orders = context.getBean("orders", Orders.class);System.out.println(orders);Orders orders1 = context.getBean("orders", Orders.class);System.out.println(orders1);}
}

3.测试多实例:地址不同

<?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"><!--通过scope属性配置单实例、多实例--><bean id="orders" class="com.qcby.spring.scope.Orders"scope="prototype"></bean>
</beans>

bean的生命周期

1.bean对象创建(调用无参构造器)

2.给bean对象设置相关属性

3.bean的后置处理器(初始化之前)

4.bean对象初始化(需在配置bean时指定初始化方法)

5.bean的后置处理器(初始化之后)

6.bean对象就绪可以使用

7.bean对象销毁(需在配置bean时指定销毁方法)

8.IoC容器关闭

演示:

package com.qcby.spring.life;public class User {private String name;//无参构造public User() {System.out.println("1.bean对象创建,调用无参构造");}public String getName() {return name;}public void setName(String name) {System.out.println("2.给bean设置属性值");this.name = name;}//初始化的方法public void  initMethod(){System.out.println("4.bean对象初始化,调用指定的初始化的方法");}//销毁的方法public void destroyMethod(){System.out.println("7.bean对象销毁,调用指定的销毁的方法");}}

bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行  

package com.qcby.spring.life;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;public class MyBeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("3.bean后置处理器,初始化之前执行");System.out.println(beanName+"::"+bean);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("5.bean后置处理器,初始化之后执行");System.out.println(beanName+"::"+bean);return bean;}}
<?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="com.qcby.spring.life.User"scope="singleton" init-method="initMethod" destroy-method="destroyMethod"><property name="name" value="lucy"></property></bean><!-- bean的后置处理器要放入IOC容器才能生效 --><bean id="myBeanProcessor" class="com.qcby.spring.life.MyBeanPost"/>
</beans>
package com.qcby.spring;import com.qcby.spring.life.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean_life.xml");User user = context.getBean("user", User.class);System.out.println("6.bean对象创建完成,可以使用");System.out.println(user);context.close();}
}

FactoryBean

FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们,将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的

演示:

package com.qcby.spring.factorybean;import org.springframework.beans.factory.FactoryBean;public class MyFactoryBean implements FactoryBean<User> {@Overridepublic User getObject() throws Exception {return new User();}@Overridepublic Class<?> getObjectType() {return User.class;}
}
<?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="com.qcby.spring.factorybean.MyFactoryBean"></bean>
</beans>
package com.qcby.spring;import com.qcby.spring.factorybean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser1 {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("bean_factorybean.xml");User user = (User) context.getBean("user");System.out.println(user);}
}

基于xml自动装配

自动装配:根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或接口类型属性赋值

使用bean标签的autowire属性设置自动装配效果

1.自动装配方式:byType(找的是class)

byType:根据类型匹配IOC容器中的某个兼容类型的bean,为属性自动赋值

若在IOC中,没有任何一个兼容类型的bean能够为属性赋值,则该属性不装配,即值为默认值null

若在IOC中,有多个兼容类型的bean能够为属性赋值,则抛出异常NoUniqueBeanDefinitionException

2.自动装配方式:byName(找的是id)

byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值

byType演示:

package com.qcby.spring.auto.controller;import com.qcby.spring.auto.service.UserService;
import com.qcby.spring.auto.service.UserServiceImpl;public class UserController {private UserService userService;public void setUserService(UserService userService) {this.userService = userService;}public void addUser(){System.out.println("controller中的方法执行了");//调用service的方法userService.addUserService();}
}
package com.qcby.spring.auto.service;public interface UserService {public void addUserService();
}
package com.qcby.spring.auto.service;import com.qcby.spring.auto.dao.UserDao;
import com.qcby.spring.auto.dao.UserDaoImpl;public class UserServiceImpl implements UserService{private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void addUserService() {System.out.println("userService中的方法执行了");//调用dao中的方法userDao.addUserDao();}
}
package com.qcby.spring.auto.dao;public interface UserDao {public void addUserDao();
}
package com.qcby.spring.auto.dao;public class UserDaoImpl implements UserDao{@Overridepublic void addUserDao() {System.out.println("userDao中的方法执行了");}
}
<?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="userController" class="com.qcby.spring.auto.controller.UserController"autowire="byType"></bean><bean id="userService" class="com.qcby.spring.auto.service.UserServiceImpl"autowire="byType"></bean><bean id="userDao" class="com.qcby.spring.auto.dao.UserDaoImpl"></bean>
</beans>
package com.qcby.spring;import com.qcby.spring.auto.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestUser1 {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("bean_auto.xml");UserController controller = context.getBean("userController", UserController.class);controller.addUser();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1534871.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于OpenSSL的密码管理系统-应用密码学课程报告

第1章 概要设计 1.1 设计目的 本研究旨在设计并实现一个基于OpenSSL的密码管理系统&#xff0c;该系统具备密钥对的生成、密钥上传、密钥的核对、身份认证、文件与邮件的加密和解密、数字签名及数字证书管理等常用功能。研究的意义主要体现在以下几个方面&#xff1a; 提升网…

M3U8是什么,如何解析下载

M3U8是什么&#xff1f;如何解析下载 M3U8是苹果公司推出的视频播放标准&#xff0c;准确来说是一种索引文件&#xff0c;使用M3U8文件实际上是通过它来解析对应的放在服务器上的视频网络地址&#xff0c;从而实现在线播放。M3U8文件使用UTF-8字符编码。M3U8是一种常见的流媒体…

互联网巨头的默契

​转载&#xff1a;树龙谈 作者&#xff1a;贺树龙 2024年的第二季度财报&#xff0c;大部分互联网公司都已经发布了。 分析已上市、最值钱的10家中国互联网公司的财报&#xff0c;不难发现这些相似之处&#xff1a; 1.它们的营收增长比较乏力&#xff1b; 2.它们的净利润增长…

工作流技术(WorkFlow)

什么是工作流 1.使用编程语言完成一套固定的审批流程 例如请假审批流程 订单配送流程 入职&#xff0c;辞职审批流程 2.使用场景 业务类&#xff1a;合同审批流程、订单处理流程、出入库审批流程等。 行政类&#xff1a;请假流程、出差流程、用车流程、办公用品申请流程…

dedecms(四种webshell姿势)

步骤一&#xff0c;登录网站 步骤二&#xff0c;进入后台 账号密码同为admin 姿势一&#xff0c;通过文件管理器上传WebShell 登陆到后台点击 【核心】--》【文件式管理器】【文件上传】 将准备好的一句话代码上传...OK 1.我们先创建一个1.php上传 2.上传之后我们双击1.php 3…

还有人认为C++容器是线程安全的吗?

C标准库中的容器&#xff08;如std::vector, std::list, std::map等&#xff09;本身不是线程安全的、不是线程安全的、不是线程安全的&#xff0c;重要的事情讲三遍。这意味着如果你在多线程环境中同时访问&#xff08;读或写&#xff09;同一个容器实例&#xff0c;而没有进行…

【二叉树的最大深度】带你理解递归奥妙!

&#x1f680;个人主页&#xff1a;一颗小谷粒 &#x1f680;所属专栏&#xff1a;力扣刷题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 &#x1f4a5;1.1 题目要求 ​&#x1f4a5;1.2 算法思路 &#x1f4a5;1.3 图解分析 &#x1…

elementui组件el-upload实现批量文件上传

el-upload组件上传文件时&#xff0c;每传一个文件会调一次接口&#xff0c;所以当上传多个文件的时候&#xff0c;有 n 个文件就要调 n 次接口。 刚好之前工作中遇到使用el-upload组件批量上传文件的需求&#xff0c;来看看怎么实现。 思路&#xff1a; 1.取消组件的自动上…

Springboot项目总结

1.为了调用写在其他包里面的类的方法 但是不使用new来实现调用这个类里面的方法&#xff0c;这个时候我们就需要将这个类注入到ioc容器里面&#xff0c;通过ioc容器来实现自动生成一个对象。 对ioc容器的理解&#xff1a;自动将一个对象实现new. 考察了and 和 or组合使用&…

[docker]入门

本文章主要讲述的是&#xff0c;docker基本实现原理&#xff0c;docker概念的解释&#xff0c;docker的使用场景以及docker打包与部署的应用。 文章中docker所运行的系统&#xff1a;CentOS Linux release 7.9.2009 (Core) 目录 docker是什么&#xff0c;什么时候需要去使用 …

房产销售系统:SpringBoot技术优势分析

第三章 系统分析 3.1 系统设计目标 房产销售系统主要是为了用户方便对房源信息管理、房源类型管理、房子户型管理、交易订单管理、预约看房管理、评价管理等信息进行查询&#xff0c;也是为了更好的让管理员进行更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各…

5.安卓逆向-java面向对象

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 上一个内容&#xff1a;4.安卓逆向-常用数据结构java语言中的集合 之前的内容写了java语言常用的数据结构&#xff08…

OpenAI o1:AI领域的“草莓”革命,华人科学家贡献卓越

最近&#xff0c;科技界的热门明星“草莓”频繁出现在大家的视线中。9月11号&#xff0c;The Information报道称&#xff1a;OpenAI计划在未来两周内推出一款更智能、更昂贵、更谨慎的AI模型&#xff01;网友们对此消息持怀疑态度&#xff0c;认为类似消息屡见不鲜&#xff0c;…

创新数字生态:智慧园区的益处与影响

智慧园区是一种利用先进信息技术、智能设备和数据分析手段来提升管理效率、改善居住体验、节约资源以及推动可持续发展的新型城市发展模式。其好处和影响不仅局限于提高工作效率&#xff0c;还涉及社会、生态、经济等多个方面的积极影响。 好处 智能化管理优势: 智慧园区能够实…

mac上Charles怎么配置,可以抓取浏览器/IDEA的接口

一、抓取浏览器接口 1、下载安装Charles后&#xff0c;按下图操作安装证书&#xff0c;mac撒好难过要把证书调整为可信任 2、打开macOS代理 方式一&#xff1a;指点开启这里 方式二&#xff1a;进入代理配置中开启&#xff0c;结果和方式一一样的 3、这时就可以抓取到浏览器…

编写注册接口与登录认证

编写注册接口 在UserController添加方法 PostMapping("/login")public Result login(Pattern(regexp "^\\S{5,16}$") String username,Pattern(regexp "^\\S{5,16}$") String password){ // 根据用户名查询用户User loginUser userS…

8个前端库-小且美

前提&#xff1a;前端有很多小而美的库&#xff0c;接入成本很低又能满足日常开发需求&#xff0c;同时无论是 npm 方式引入还是直接复制到本地使用都可以。 1.radash radash相比与 lodash&#xff0c;更加面向现代&#xff0c;提供更多新功能&#xff08;tryit&#xff0c;…

系统架构设计师教程 第5章 5.2需求工程 笔记

5.2 需求工程 ★★★★★ 软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。 软件需求包括3个不同的层次&#xff1a;业务需求、用户需求和功能需求(也包括非功能需求)。 (1)业务需求 (business requirement) 反映了组织机构或客户对系统、产品高层次的目标…

哪款宠物空气净化器是除浮毛王者?希喂、范罗士、霍尼韦尔宠物空气净化器实测

养宠人绕不过的痛——掉毛&#xff01;脱毛&#xff01;又到了掉毛季&#xff0c;就连空气中都有毛毛……不管遇到谁&#xff0c;都知道你养猫养狗了——只因T恤变身毛线衫、毛毛怎么都粘不干净。不止是衣服上&#xff0c;地板上、沙发上、桌面上&#xff0c;哪哪都是毛。开始养…

[产品管理-15]:NPDP新产品开发 - 13 - 产品创新流程 - 具体产品的创新流程:精益生产与敏捷开发

目录 前言&#xff1a;​ 一、集成产品开发IPD模型——集成跨功能团队的产品开发 1.1 概述 1、IPD模型的核心思想 2、IPD模型的主要组成部分 3、IPD模型的实施步骤 4、IPD模型的优点 1.2 基于IPD系统的组织实践等级 1.3 IPD的优缺点 二、瀑布开发模型 1、定义与特点…