文章目录
前言
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; } publicStringtoString() { 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>
④测试
publicvoidtestBeanScope(){ 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、销毁"); } publicStringtoString() { 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>
④测试
publicvoidtestLife(){ 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 { publicObjectpostProcessBeforeInitialization(Objectbean, StringbeanName) throwsBeansException { System.out.println("☆☆☆"+beanName+" = "+bean); returnbean; } publicObjectpostProcessAfterInitialization(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*/TgetObject() 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*/Class<?>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> { publicUsergetObject() throwsException { returnnewUser(); } publicClass<?>getObjectType() { returnUser.class; } }
③配置bean
<beanid="user"class="com.atguigu.spring6.bean.UserFactoryBean"></bean>
④测试
publicvoidtestUserFactoryBean(){ //获取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; } publicvoidsaveUser() { userDao.saveUser(); } }
创建接口UserDao
packagecom.atguigu.spring6.autowire.daopublicinterfaceUserDao { voidsaveUser(); }
创建类UserDaoImpl实现接口UserDao
packagecom.atguigu.spring6.autowire.dao.implpublicclassUserDaoImplimplementsUserDao { publicvoidsaveUser() { 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>
③测试
publicvoidtestAutoWireByXML(){ ApplicationContextac=newClassPathXmlApplicationContext("autowire-xml.xml"); UserControlleruserController=ac.getBean(UserController.class); userController.saveUser(); }
总结
以上就是Spring之容器:IOC(3)的相关知识点,希望对你有所帮助。
积跬步以至千里,积怠惰以至深渊。时代在这跟着你一起努力哦!