Spring之容器:IOC(3)

本文涉及的产品
应用实时监控服务-用户体验监控,每月100OCU免费额度
可观测可视化 Grafana 版,10个用户账号 1个月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 【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)的相关知识点,希望对你有所帮助。

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


相关文章
|
23天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
14天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
28 0
|
2月前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
128 9
|
1月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
32 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
2月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
40 4
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
67 0
|
2月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
125 3
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
48 0
下一篇
无影云桌面