一起学SF框架系列5.3-模块Beans-bean与Spring容器的交互方式

news2024/11/23 11:12:32

  正常情况下,应用中的bean同spring容器关系如下图:
在这里插入图片描述

尽管应用bean是Spring容器创建并建立依赖关系,应用只需使用bean即可,因此对bean来说Spring容器就是无感知的(无侵入编程)。但是还是存在需求需要应用bean同Spring容器进行交互,以便利用容器的能力完成相关工作。本篇就是讲述应用Bean如何与容器进行交互的。

创建

Bean实例化详细过程

框架加载BeanDefiniation,初始化容器环境,然后进行Bean的实例化:
1、如果有实现BeanPostProcessor的bean,则优先创建;
2、框架选择合适的Bean构建函数,创建Bean对象;
3、框架设置Bean属性;
4、如果bean实现了Aware接口,则执行;
5、如果存在BeanPostProcessor类,则执行postProcessBeforeInitialization;
6、如果bean有初始化方法(@PostConstruct标注或xml配置),则执行;
7、如果Bean实现了InitializingBean接口,则会调用afterPropertiesSet方法;
8、如果存在BeanPostProcessor类,则执行postProcessAfterInitialization;
9、如果bean有SmartInitializingSingleton,则在所有单实例bean实例化后执行afterSingletonsInstantiated
上述过程中存在“如果”的地方,就意味着应用可与容器交互的地方。

BeanPostProcessor

BeanPostProcessor接口主要是在bean初始化前后,应用可加入自己处理。注意:该类是针对所有应用bean的,因此处理时可根据Bean类做处理。
示例代码如下:

@Component
public class DemoBeanPostProcessor implements BeanPostProcessor {
	ApplicationContext ctx;

	DemoBeanPostProcessor(){
		System.out.println("Spring DemoBeanPostProcessor contructing...");
	}

	//---------------------------------------------------------------------
	// Implementation of BeanPostProcessor interface
	//---------------------------------------------------------------------
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// 可根据beanName 或 instanceof 针对性处理
		System.out.println("Spring DemoBeanPostProcessor postProcessBeforeInitialization "+beanName+": "+bean);
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("Spring DemoBeanPostProcessor postProcessAfterInitialization "+beanName+": "+bean);
		return bean;
	}
}

Aware

感知类接口(接口名称格式:xxxAware),让实现的类可以感知容器的某些能力。SF的依赖注入亮点之一就是所有的Bean实现时都不需要考虑运行时要如何注入Spring容器(就是无感知),Bean和Spring容器耦合度很低(就是无侵入编程)。实际开发的时候,有时Bean需要用到Spring容器本身的功能资源,就需要提供一种机制让Bean能意识到Spring容器到存在并能调用Spring所提供的资源,这个机制就是由Aware来实现的。示例代码如下:

@Component
public class DemoAware implements ApplicationContextAware{
    //ctx在初始化过程中通过Aware方式注入
	ApplicationContext ctx;
	
	//---------------------------------------------------------------------
	// Implementation of ApplicationContextAware interface
	//---------------------------------------------------------------------
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{
		System.out.println("DemoAware set ApplicationContextAware");
		this.app = applicationContext;
		System.out.println(app);
	}
}

详见:https://blog.csdn.net/davidwkx/article/details/130790874

初始化方法(@PostConstruct)

bean的初始化方法在框架加载中会执行,标注初始化方法有两种:注解@PostConstruct或xml。
注解方式示例如下:

	@PostConstruct
	public void init() {
		System.out.println("DemoInteractiveInInitialing init");	
	}

xml方式配置如下:

<bean id = "demoInteractiveInInitialing " class="com.learnsf.demo.spring.DemoInteractiveInInitialing " init-method="init"></bean>

afterPropertiesSet

InitializingBean接口定义了方法afterPropertiesSet,表示在Bean的属性设置后执行。
示例代码如下:

@Component
public class DemoInitializingBean implements InitializingBean{

	//---------------------------------------------------------------------
	// Implementation of InitializingBean interface
	//---------------------------------------------------------------------
	public void afterPropertiesSet() {
		System.out.println("DemoInteractiveInInitialing afterPropertiesSet ");
	}

}

afterSingletonsInstantiated

SmartInitializingSingleton接口定义了方法afterSingletonsInstantiated,表示所有单例bean初始化后执行。
示例代码如下:

@Component
public class DemoSmartInitializingSingleton implements SmartInitializingSingleton{
	//---------------------------------------------------------------------
	// Implementation of SmartInitializingSingleton interface
	//---------------------------------------------------------------------
	public void afterSingletonsInstantiated(){
		System.out.println("DemoSmartInitializingSingleton::SmartInitializingSingleton在该类构建后被触发执行");
	}
}

应用中

Aware

在bean初始化过程通过Aware方式获得相关容器资源,直接使用即可。

MethodInterceptor

通过实现接口MethodInterceptor,可在执行方法前后做其它处理。
示例代码如下:

@Component
public class ProxyInterceptor implements MethodInterceptor {
	private String className;
	private String methodName;
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    	className=o.getClass().getName();
    	methodName=methodProxy.getSuperName();//method.getName(); 
    	
        before();
        
        //调用被代理类的方法
        Object result = methodProxy.invokeSuper(o, objects);
        
        after();
        
        return result;
    }
    // 预处理方法
    private void before() {
        System.out.println(String.format("%s.%s before excute: [%s] ",this.className, this.methodName,new Date()));
    }
        // 后处理方法
    private void after() {
        System.out.println(String.format("%s.%s after excute: [%s] ",this.className, this.methodName, new Date()));
    }
}

AOP注解

通过AOP注解和实现完成所需工作。

销毁

bean销毁前,bean可以有两种方式介入:继承DisposableBean接口或@PreDestroy或xml模式配置。

DisposableBean / @PreDestroy

应用bean可在实现org.springframework.beans.factory.DisposableBean接口中完成销毁前工作。

@Component
@Scope("singleton")
public class DemoDisposableBean implements DisposableBean{
	//---------------------------------------------------------------------
	// Implementation of DisposableBean interface
	//---------------------------------------------------------------------
	@Override
	public void destroy()  throws Exception{
		System.out.println("DemoDisposableBean destory start... ");	
	}
	@PreDestroy
	public void preDestory()  throws Exception{
		System.out.println("DemoDisposableBean @PreDestory start... ");	
	}
}

xml配置

<bean id = "DemoDisposableBean" class="com.learnsf.demo.spring.DemoDisposableBean" destory-method="destroy"></bean>

destory()方法不生效原因

实际使用可能出现destory()方法不起作用,有以下原因导致:
1、bean的作用域必须是单例的(singleton),不能是prototype。
2、容器没有正常关闭:如果容器不在Servlet或者EJB容器中,需要手动调用ApplicationContext子类中的close()方法,去实现相应关闭的功能。
示例如下:

public class LearnMain {
    public static void main(String[] args) {
        //创建springframework容器,初始化文件为app.xml
    	ApplicationContext context = new ClassPathXmlApplicationContext("app.xml");

		...
		        
        //容器关闭才能执行bean。destory()方法
        ((ClassPathXmlApplicationContext)context).close();
    }
}

特殊FactoryBean

大多数情况下,应用bean都由SF的BeanFactory实例化和管理。但如果应用有需要,可以通过的自己工厂bean(FactoryBean)创建bean。FactoryBean需实现接口FactoryBean或SmartFactoryBean,T就是FactoryBean要创建的Bean。
FactoryBean被容器加载后,然后执行getObject()获得bean,容器就完成使命了,也不再执行“Bean实例化详细过程”(见本文第一节)第三步开始的内容。
下面是一个FactoryBean实例:

@Component("studentFacoryBean")
public class StudentFacoryBean implements FactoryBean<Student>{
    private static final String STUDENT_NAME = "Zhangsan";
    public Student getObject() {
    	Student student = new Student();
    	student.setName(STUDENT_NAME);
        return student;
    }
    public Class<?> getObjectType() {
        return Student.class;
    }
}

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

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

相关文章

OkHttp 框架设计剖析(含面试题)

作者&#xff1a;Calculus_小王 概述 OKHttp是一个基于HTTP协议的网络请求框架&#xff0c;它支持HTTP/2协议&#xff0c;连接复用和连接池&#xff0c;缓存策略等功能。它的核心设计是拦截器&#xff08;Interceptor&#xff09;&#xff0c;它将请求的复杂逻辑切分成多个独立…

详解Java内部类、匿名内部类

内部类 内部类&#xff1a;类的第五个成员 1.定义&#xff1a;Java中允许将一个类A声明在另一个类B中&#xff0c;则类A就是内部类&#xff0c;类B称为外部类. 2.内部类的分类&#xff1a; 成员内部类&#xff08;静态、非静态 &#xff09; vs 局部内部类(方法内、代码块内、…

全网最强总结,Selenium自动化测试异常+处理总结,吐血整理...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 当测试工程师执行…

LVS负载均衡群集部署——DR模式

LVS负载均衡群集部署——DR模式 一、LVS-DR集群概述1、LVS-DR 工作原理2、LVS-DR数据包流量分析&#xff08;同一局域网&#xff09;3、LVS-DR中的ARP问题4、LVS-DR处理问题后的流量分析5、LVS-DR 特性 二、构建LVS-DR集群1、构建LVS-DR集群的步骤&#xff08;理论&#xff09;…

网工内推 | 网安专场,CISP认证优先,带薪年假,六险一金

01 MATRIX TECH &#x1f537;招聘岗位&#xff1a;安全工程师 &#x1f537;职责描述&#xff1a; 1、负责信息安全防护系统的日常管理 、监测和优化提升等安全运营工作&#xff0c;包括终端安全、防护、漏洞检测、补丁、入侵检测、拒绝服务攻击防护、源代码安全检查等&#…

cool-admin框架后端使用-node版本,线上宝塔部署

版本6.x 宝塔新建一个文件夹和创建好数据库&#xff0c;记录账号和密码&#xff0c;自行创建&#xff0c;不做说明 特别注意&#xff0c;如果用宝塔node管理那里运行&#xff0c;如果按照到有pm2的&#xff0c;要先卸载&#xff0c;不可以共存&#xff0c;会有冲突 cool-vue前端…

.gitignore忽略文件不生效

前言 .gitignore忽略文件时git仓库很重要的一个配置&#xff0c;在创建仓库时就会有模板选择和忽略文件。 .gitignore忽略文件意思是在上传到代码仓库时&#xff0c;控制把哪些代码文件不上传到代码仓库。 在实际开发中其实写的代码是没有多大的&#xff0c;主要的是插件本地…

凸优化系列——最优化问题

1. 凸优化问题介绍 凸优化问题如下&#xff1a; 为什么要求不等式约束是线性函数呢&#xff1f;我们知道凸函数的下水平集是凸集。 为什么要求等式约束是线性的呢&#xff1f;线性函数表示一个超平面&#xff0c;他也是凸集 也就是说&#xff0c;对于凸优化问题&#xff0c;…

《Lua程序设计》--学习4

闭包 在Lua语言中&#xff0c;函数是严格遵循词法定界&#xff08;lexicalscoping&#xff09;的第一类值&#xff08;first-classvalue&#xff09;。 “第一类值”意味着Lua语言中的函数与其他常见类型的值&#xff08;例如数值和字符串&#xff09;具有同等权限&#xff1…

Proteus仿真之LCD1602

1.项目简介&#xff1a;利用Proteus仿真在LCD1602上显示字母。 2.设计思路&#xff1a;首先要读懂LCD1602的时序图和每一个端口高低电平时的含义。 然后&#xff0c;通过操作的端口的高低电平来达到操作数据的目的。主要思路是&#xff0c;根据端口的组合来&#xff0c;将数据…

信号原理解析

目录 一、什么是信号 举例子&#xff1a; 进程如何认识信号 信号与进程的异步 进程如何储存信号 二、一个实例 signal函数&#xff1a; 三、实例后的思考 一个进程接受到信号后&#xff0c;处理信号的方法&#xff1a; myhandler什么时候才会被调用 四、理解ctrlc被…

【spring源码系列-04】注解方式启动spring时refresh的前置工作

Spring源码系列整体栏目 内容链接地址【一】spring源码整体概述https://blog.csdn.net/zhenghuishengq/article/details/130940885【二】通过refresh方法剖析IOC的整体流程https://blog.csdn.net/zhenghuishengq/article/details/131003428【三】xml配置文件启动spring时refres…

第五十回:TabBarView Widget

文章目录 概念介绍使用方法示例代码综合使用 我们在上一章回中介绍了DefaultTabBarController Widget相关的内容,本章回中将介绍 TabBarView Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们这里介绍的TabBarView类似前面章回中介绍过的PageView组件&a…

应对数据不平衡和过拟合的分类模型优化策略

不平衡分类 数据类别不平衡问题是指数据集中各类别样本数量不对等的情况。 基于抽样的方法 在处理这类问题时&#xff0c;可以采用基于抽样的方法来解决。以下是几种常见的基于抽样的方法&#xff1a; 两阶段学习 两阶段学习是一种解决不平衡分类问题的方法&#xff0c;包括…

软件测试 之Web项目实战解析(附全套实战项目教程+视频+源码)

软件测试之web项目实战 按顺序依次为&#xff1a;【搭建测试环境】、【需求评审】、【编写测试计划】、【分析测试点.编写测试用例】、【用例评审】、【执行用例提bug】、【测试报告】 一&#xff1a;搭建测试环境 (1) 搭建测试环境之 【常见项目结构模式】 &#xff08;2&am…

【大数据之路3】分布式协调系统 Zookeeper

3. 分布式协调系统 Zookeeper 1. Zookeeper 概述1. Zookeeper 介绍2. Zookeeper 结构/功能【重点】1. 文件系统 ZNode1. ZNode 特点2. ZNode 功能3. ZNode 介绍【非常重要】 2. 监听机制 3. 典型应用场景1. 命名服务2. 配置管理3. 集群管理4. 分布式锁5. 队列管理 2. 架构与原理…

MaskRCNN与注意力机制

Mask RCNN---two stage mask rcnn是一个分割算法(实例分割)&#xff0c;可用于&#xff1a; 目标检测 实例分割 关键点检测 本质上&#xff0c;mask R-CNN是在faster rcnn的基础上&#xff0c;加入了FCN模块&#xff0c;得到最终的分割结果。 先检测&#xff0c;再分割。不…

实战:在Docker上部署Springboot项目(附源码)

实战&#xff1a;在Docker上部署Springboot项目&#xff08;附源码&#xff09; 1、docker的基本使用 1、为什么使用docker 2、docker的介绍 3、docker安装 https://www.codezhou.top/article/docker%E4%BD%BF%E7%94%A8 2、dockers安装mysql 拉取 Mysql 5.7.31 镜像 dock…

手工测试没有前途,自动化测试会取代手工测试?

在测试行业&#xff0c;一个一直被讨论的问题就是&#xff1a;手工测试没有前途&#xff0c;自动化测试会取代手工测试&#xff1f; 首先说结论&#xff1a;自动化测试不会取代手工测试&#xff0c;这完全是两个维度的事情。为什么不会呢&#xff1f;我们需要从本源上说起。 什…

【数据挖掘实战】——舆情分析:对微博文本进行情绪分类

&#x1f935;‍♂️ 个人主页&#xff1a;Lingxw_w的个人主页 ✍&#x1f3fb;作者简介&#xff1a;计算机科学与技术研究生在读 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4a…