Spring之容器:IOC(3)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: 【1月更文挑战第14天】11、实验十:bean的作用域12、实验十一:bean生命周期13、实验十二:FactoryBean14、实验十三:基于xml自动装配

文章目录

前言

11、实验十:bean的作用域

12、实验十一:bean生命周期

13、实验十二:FactoryBean

14、实验十三:基于xml自动装配

总结


前言

11、实验十:bean的作用域

12、实验十一:bean生命周期

13、实验十二:FactoryBean

14、实验十三:基于xml自动装配


11、实验十:bean的作用域

①概念

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

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

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

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

②创建类User

packagecom.atguigu.spring6.bean;
publicclassUser {
privateIntegerid;
privateStringusername;
privateStringpassword;
privateIntegerage;
publicUser() {
    }
publicUser(Integerid, Stringusername, Stringpassword, Integerage) {
this.id=id;
this.username=username;
this.password=password;
this.age=age;
    }
publicIntegergetId() {
returnid;
    }
publicvoidsetId(Integerid) {
this.id=id;
    }
publicStringgetUsername() {
returnusername;
    }
publicvoidsetUsername(Stringusername) {
this.username=username;
    }
publicStringgetPassword() {
returnpassword;
    }
publicvoidsetPassword(Stringpassword) {
this.password=password;
    }
publicIntegergetAge() {
returnage;
    }
publicvoidsetAge(Integerage) {
this.age=age;
    }
@OverridepublicStringtoString() {
return"User{"+"id="+id+", username='"+username+'\''+", password='"+password+'\''+", age="+age+'}';
    }
}

③配置bean

<!-- scope属性:取值singleton(默认值),bean在IOC容器中只有一个实例,IOC容器初始化时创建对象 --><!-- scope属性:取值prototype,bean在IOC容器中可以有多个实例,getBean()时创建对象 --><beanclass="com.atguigu.spring6.bean.User"scope="prototype"></bean>

④测试

@TestpublicvoidtestBeanScope(){
ApplicationContextac=newClassPathXmlApplicationContext("spring-scope.xml");
Useruser1=ac.getBean(User.class);
Useruser2=ac.getBean(User.class);
System.out.println(user1==user2);
}

12、实验十一:bean生命周期

①具体的生命周期过程

  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean的后置处理器(初始化之前)
  • bean对象初始化(需在配置bean时指定初始化方法)
  • bean的后置处理器(初始化之后)
  • bean对象就绪可以使用
  • bean对象销毁(需在配置bean时指定销毁方法)
  • IOC容器关闭

②修改类User

publicclassUser {
privateIntegerid;
privateStringusername;
privateStringpassword;
privateIntegerage;
publicUser() {
System.out.println("生命周期:1、创建对象");
    }
publicUser(Integerid, Stringusername, Stringpassword, Integerage) {
this.id=id;
this.username=username;
this.password=password;
this.age=age;
    }
publicIntegergetId() {
returnid;
    }
publicvoidsetId(Integerid) {
System.out.println("生命周期:2、依赖注入");
this.id=id;
    }
publicStringgetUsername() {
returnusername;
    }
publicvoidsetUsername(Stringusername) {
this.username=username;
    }
publicStringgetPassword() {
returnpassword;
    }
publicvoidsetPassword(Stringpassword) {
this.password=password;
    }
publicIntegergetAge() {
returnage;
    }
publicvoidsetAge(Integerage) {
this.age=age;
    }
publicvoidinitMethod(){
System.out.println("生命周期:3、初始化");
    }
publicvoiddestroyMethod(){
System.out.println("生命周期:5、销毁");
    }
@OverridepublicStringtoString() {
return"User{"+"id="+id+", username='"+username+'\''+", password='"+password+'\''+", age="+age+'}';
    }
}

注意其中的initMethod()和destroyMethod(),可以通过配置bean指定为初始化和销毁的方法

③配置bean

<!-- 使用init-method属性指定初始化方法 --><!-- 使用destroy-method属性指定销毁方法 --><beanclass="com.atguigu.spring6.bean.User"scope="prototype"init-method="initMethod"destroy-method="destroyMethod"><propertyname="id"value="1001"></property><propertyname="username"value="admin"></property><propertyname="password"value="123456"></property><propertyname="age"value="23"></property></bean>

④测试

@TestpublicvoidtestLife(){
ClassPathXmlApplicationContextac=newClassPathXmlApplicationContext("spring-lifecycle.xml");
Userbean=ac.getBean(User.class);
System.out.println("生命周期:4、通过IOC容器获取bean并使用");
ac.close();
}

⑤bean的后置处理器

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

创建bean的后置处理器:

packagecom.atguigu.spring6.process;
importorg.springframework.beans.BeansException;
importorg.springframework.beans.factory.config.BeanPostProcessor;
publicclassMyBeanProcessorimplementsBeanPostProcessor {
@OverridepublicObjectpostProcessBeforeInitialization(Objectbean, StringbeanName) throwsBeansException {
System.out.println("☆☆☆"+beanName+" = "+bean);
returnbean;
    }
@OverridepublicObjectpostProcessAfterInitialization(Objectbean, StringbeanName) throwsBeansException {
System.out.println("★★★"+beanName+" = "+bean);
returnbean;
    }
}

在IOC容器中配置后置处理器:

<!-- bean的后置处理器要放入IOC容器才能生效 --><beanid="myBeanProcessor"class="com.atguigu.spring6.process.MyBeanProcessor"/>

13、实验十二:FactoryBean

①简介

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

将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。

/** Copyright 2002-2020 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/packageorg.springframework.beans.factory;
importorg.springframework.lang.Nullable;
/*** Interface to be implemented by objects used within a {@link BeanFactory} which* are themselves factories for individual objects. If a bean implements this* interface, it is used as a factory for an object to expose, not directly as a* bean instance that will be exposed itself.** <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>* A FactoryBean is defined in a bean style, but the object exposed for bean* references ({@link #getObject()}) is always the object that it creates.** <p>FactoryBeans can support singletons and prototypes, and can either create* objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}* interface allows for exposing more fine-grained behavioral metadata.** <p>This interface is heavily used within the framework itself, for example for* the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the* {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for* custom components as well; however, this is only common for infrastructure code.** <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not* supposed to rely on annotation-driven injection or other reflective facilities.</b>* {@link #getObjectType()} {@link #getObject()} invocations may arrive early in the* bootstrap process, even ahead of any post-processor setup. If you need access to* other beans, implement {@link BeanFactoryAware} and obtain them programmatically.** <p><b>The container is only responsible for managing the lifecycle of the FactoryBean* instance, not the lifecycle of the objects created by the FactoryBean.</b> Therefore,* a destroy method on an exposed bean object (such as {@link java.io.Closeable#close()}* will <i>not</i> be called automatically. Instead, a FactoryBean should implement* {@link DisposableBean} and delegate any such close call to the underlying object.** <p>Finally, FactoryBean objects participate in the containing BeanFactory's* synchronization of bean creation. There is usually no need for internal* synchronization other than for purposes of lazy initialization within the* FactoryBean itself (or the like).** @author Rod Johnson* @author Juergen Hoeller* @since 08.03.2003* @param <T> the bean type* @see org.springframework.beans.factory.BeanFactory* @see org.springframework.aop.framework.ProxyFactoryBean* @see org.springframework.jndi.JndiObjectFactoryBean*/publicinterfaceFactoryBean<T> {
/*** The name of an attribute that can be* {@link org.springframework.core.AttributeAccessor#setAttribute set} on a* {@link org.springframework.beans.factory.config.BeanDefinition} so that* factory beans can signal their object type when it can't be deduced from* the factory bean class.* @since 5.2*/StringOBJECT_TYPE_ATTRIBUTE="factoryBeanObjectType";
/*** Return an instance (possibly shared or independent) of the object* managed by this factory.* <p>As with a {@link BeanFactory}, this allows support for both the* Singleton and Prototype design pattern.* <p>If this FactoryBean is not fully initialized yet at the time of* the call (for example because it is involved in a circular reference),* throw a corresponding {@link FactoryBeanNotInitializedException}.* <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}* objects. The factory will consider this as normal value to be used; it* will not throw a FactoryBeanNotInitializedException in this case anymore.* FactoryBean implementations are encouraged to throw* FactoryBeanNotInitializedException themselves now, as appropriate.* @return an instance of the bean (can be {@code null})* @throws Exception in case of creation errors* @see FactoryBeanNotInitializedException*/@NullableTgetObject() throwsException;
/*** Return the type of object that this FactoryBean creates,* or {@code null} if not known in advance.* <p>This allows one to check for specific types of beans without* instantiating objects, for example on autowiring.* <p>In the case of implementations that are creating a singleton object,* this method should try to avoid singleton creation as far as possible;* it should rather estimate the type in advance.* For prototypes, returning a meaningful type here is advisable too.* <p>This method can be called <i>before</i> this FactoryBean has* been fully initialized. It must not rely on state created during* initialization; of course, it can still use such state if available.* <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return* {@code null} here. Therefore it is highly recommended to implement* this method properly, using the current state of the FactoryBean.* @return the type of object that this FactoryBean creates,* or {@code null} if not known at the time of the call* @see ListableBeanFactory#getBeansOfType*/@NullableClass<?>getObjectType();
/*** Is the object managed by this factory a singleton? That is,* will {@link #getObject()} always return the same object* (a reference that can be cached)?* <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,* the object returned from {@code getObject()} might get cached* by the owning BeanFactory. Hence, do not return {@code true}* unless the FactoryBean always exposes the same reference.* <p>The singleton status of the FactoryBean itself will generally* be provided by the owning BeanFactory; usually, it has to be* defined as singleton there.* <p><b>NOTE:</b> This method returning {@code false} does not* necessarily indicate that returned objects are independent instances.* An implementation of the extended {@link SmartFactoryBean} interface* may explicitly indicate independent instances through its* {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}* implementations which do not implement this extended interface are* simply assumed to always return independent instances if the* {@code isSingleton()} implementation returns {@code false}.* <p>The default implementation returns {@code true}, since a* {@code FactoryBean} typically manages a singleton instance.* @return whether the exposed object is a singleton* @see #getObject()* @see SmartFactoryBean#isPrototype()*/defaultbooleanisSingleton() {
returntrue;
    }
}

②创建类UserFactoryBean

packagecom.atguigu.spring6.bean;
publicclassUserFactoryBeanimplementsFactoryBean<User> {
@OverridepublicUsergetObject() throwsException {
returnnewUser();
    }
@OverridepublicClass<?>getObjectType() {
returnUser.class;
    }
}

③配置bean

<beanid="user"class="com.atguigu.spring6.bean.UserFactoryBean"></bean>

④测试

@TestpublicvoidtestUserFactoryBean(){
//获取IOC容器ApplicationContextac=newClassPathXmlApplicationContext("spring-factorybean.xml");
Useruser= (User) ac.getBean("user");
System.out.println(user);
}

14、实验十三:基于xml自动装配

自动装配:

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

①场景模拟

创建类UserController

packagecom.atguigu.spring6.autowire.controllerpublicclassUserController {
privateUserServiceuserService;
publicvoidsetUserService(UserServiceuserService) {
this.userService=userService;
    }
publicvoidsaveUser(){
userService.saveUser();
    }
}

创建接口UserService

packagecom.atguigu.spring6.autowire.servicepublicinterfaceUserService {
voidsaveUser();
}

创建类UserServiceImpl实现接口UserService

packagecom.atguigu.spring6.autowire.service.implpublicclassUserServiceImplimplementsUserService {
privateUserDaouserDao;
publicvoidsetUserDao(UserDaouserDao) {
this.userDao=userDao;
    }
@OverridepublicvoidsaveUser() {
userDao.saveUser();
    }
}

创建接口UserDao

packagecom.atguigu.spring6.autowire.daopublicinterfaceUserDao {
voidsaveUser();
}

创建类UserDaoImpl实现接口UserDao

packagecom.atguigu.spring6.autowire.dao.implpublicclassUserDaoImplimplementsUserDao {
@OverridepublicvoidsaveUser() {
System.out.println("保存成功");
    }
}

②配置bean

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

自动装配方式:byType

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

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

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

<beanid="userController"class="com.atguigu.spring6.autowire.controller.UserController"autowire="byType"></bean><beanid="userService"class="com.atguigu.spring6.autowire.service.impl.UserServiceImpl"autowire="byType"></bean><beanid="userDao"class="com.atguigu.spring6.autowire.dao.impl.UserDaoImpl"></bean>

自动装配方式:byName

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

<beanid="userController"class="com.atguigu.spring6.autowire.controller.UserController"autowire="byName"></bean><beanid="userService"class="com.atguigu.spring6.autowire.service.impl.UserServiceImpl"autowire="byName"></bean><beanid="userServiceImpl"class="com.atguigu.spring6.autowire.service.impl.UserServiceImpl"autowire="byName"></bean><beanid="userDao"class="com.atguigu.spring6.autowire.dao.impl.UserDaoImpl"></bean><beanid="userDaoImpl"class="com.atguigu.spring6.autowire.dao.impl.UserDaoImpl"></bean>

③测试

@TestpublicvoidtestAutoWireByXML(){
ApplicationContextac=newClassPathXmlApplicationContext("autowire-xml.xml");
UserControlleruserController=ac.getBean(UserController.class);
userController.saveUser();
}

总结

以上就是Spring之容器:IOC(3)的相关知识点,希望对你有所帮助。

积跬步以至千里,积怠惰以至深渊。时代在这跟着你一起努力哦!


相关文章
|
7月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
504 26
|
4月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
9月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
192 69
|
6月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
7月前
|
XML Java 数据格式
Spring容器的本质
本文主要讨论Spring容器最核心的机制,用最少的代码讲清楚Spring容器的本质。
|
9月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
9月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
142 21
|
9月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
225 12
|
9月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
254 6
|
9月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
204 2