当前位置: 首页 > news >正文

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();}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Android 源码多个Launcher设置默认Launcher
  • 『功能项目』C#拓展 - 优化冗余脚本【36】
  • 目标检测从入门到精通——数据增强方法总结
  • 使用vue2+axios+chart.js画折线图 ,出现 RangeError: Maximum call stack size exceeded 错误
  • 远程访问电脑共享文件
  • 一文说清什么是数据仓库
  • 灌区信息化建设的主要内容
  • 视频监控基础学习
  • GaN挑战Si价格底线?英飞凌推出全球首个12英寸GaN晶圆技术
  • 使用程序方式获取与处理MySQL表数据
  • [Unity Demo]从零开始制作空洞骑士Hollow Knight第二集:通过InControl插件实现绑定玩家输入以及制作小骑士移动空闲动画
  • Spring Cloud之二 微服务注册
  • JS中判断字符串中是否包含指定字符
  • 代码随想录刷题day32丨动态规划理论基础,509. 斐波那契数, 70. 爬楼梯, 746. 使用最小花费爬楼梯
  • Failed building wheel for opencv-python-headless
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • Druid 在有赞的实践
  • Go 语言编译器的 //go: 详解
  • HTML5新特性总结
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • vue中实现单选
  • 从0实现一个tiny react(三)生命周期
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 计算机在识别图像时“看到”了什么?
  • 为视图添加丝滑的水波纹
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 《天龙八部3D》Unity技术方案揭秘
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​HTTP与HTTPS:网络通信的安全卫士
  • #100天计划# 2013年9月29日
  • #java学习笔记(面向对象)----(未完结)
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (10)STL算法之搜索(二) 二分查找
  • (vue)el-tabs选中最后一项后更新数据后无法展开
  • (zhuan) 一些RL的文献(及笔记)
  • (备忘)Java Map 遍历
  • (层次遍历)104. 二叉树的最大深度
  • (十三)Flask之特殊装饰器详解
  • (四)库存超卖案例实战——优化redis分布式锁
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)PyTorch代码规范最佳实践和样式指南
  • * CIL library *(* CIL module *) : error LNK2005: _DllMain@12 already defined in mfcs120u.lib(dllmodu
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .Net下的签名与混淆
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • @RequestMapping用法详解
  • @SuppressWarnings(unchecked)代码的作用
  • [22]. 括号生成
  • [Apio2012]dispatching 左偏树
  • [ARC066F]Contest with Drinks Hard
  • [bzoj1038][ZJOI2008]瞭望塔
  • [cocos creator]EditBox,editing-return事件,清空输入框