Bean的生命周期 : 创建bean对象 – 属性赋值 – 初始化方法调用前的操作 – 初始化方法 – 初始化方法调用后的操作 – …-- 销毁前操作 – 销毁方法的调用。
【1】init-method和destroy-method
自定义初始化方法和销毁方法两种方式:xml配置和注解。
① xml配置
② 注解配置
@Scope("singleton")
@Lazy
@Bean(name="person",initMethod="init",destroyMethod="cleanUp",
autowire=Autowire.BY_NAME)
public Person person01(){
return new Person("lisi", 20);
}
单实例bean在容器创建完成前会进行创建并初始化,在容器销毁的时候进行销毁。多实例bean(scope=prototype)在第一次获取该bean实例时才会创建并初始化,且容器不负责该bean的销毁。
【2】InitializingBean 和DisposableBean
InitializingBean 接口:
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
在BeanFactory设置完bean属性后执行
需要被bean实现的接口,一旦bean的属性被BeanFactory设置后需要做出反应: 如,执行自定义初始化,或者仅仅是检查是否设置了所有强制属性。
实现InitializingBean 的可替代方式为给bean指定一个自定义的init-method,例如在一个xml bean 定义中。
在bean的属性设置之后进行操作,不返回任何值但是允许抛出异常。
DisposableBean接口:
public interface DisposableBean {
void destroy() throws Exception;
}
被bean实现的接口,在销毁时释放资源,在Bean销毁的时候调用该方法。
如果销毁一个缓存的单例,一个BeanFactory 可能会调用这个销毁方法。
在容器关闭时,应用上下文会销毁所有的单例bean。
一种替代实现DisposableBean 接口的方案为指定一个自定义的destroy-method方法,例如在一个xml bean定义中。
自定义bean实现上述两个接口
@Component
public class Cat implements InitializingBean,DisposableBean {
public Cat(){
System.out.println("cat constructor...");
}
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println("cat...destroy...");
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println("cat...afterPropertiesSet...");
}
}
测试结果
cat constructor... cat...afterPropertiesSet... 容器创建完成... 四月 08, 2018 6:35:46 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@11028347: startup date [Sun Apr 08 18:35:46 CST 2018]; root of context hierarchy cat...destroy...
【3】@PostConstruct和@PreDestroy
使用JSR250规范定义的两个注解:
@PostConstruct: PostConstruct注解作用在方法上,在依赖注入完成后进行一些初始化操作。这个方法在类被放入service之前被调用,所有支持依赖项注入的类都必须支持此注解。
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
自定义类使用上述两个注解
@Component
public class Dog implements ApplicationContextAware {
//@Autowired
private ApplicationContext applicationContext;
public Dog(){
System.out.println("dog constructor...");
}
//对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("Dog....@PostConstruct...");
}
//容器移除对象之前
@PreDestroy
public void detory(){
System.out.println("Dog....@PreDestroy...");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
}
}
测试结果如下
dog constructor... Dog....@PostConstruct... 容器创建完成... 四月 08, 2018 6:42:11 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose 信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@11028347: startup date [Sun Apr 08 18:42:10 CST 2018]; root of context hierarchy Dog....@PreDestroy...
【4】BeanPostProcessor-Bean后置处理器
① 什么是bean后置处理器
在bean初始化前后进行一些处理工作
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作
其接口源码如下:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
自定义MyBeanPostProcessor实现该接口:
/**
* 后置处理器:初始化前后进行处理工作
* 将后置处理器加入到容器中
* @author lfy
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("BeanPostProcessor.postProcessBeforeInitialization..."+beanName+"=>"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
System.out.println("BeanPostProcessor.postProcessAfterInitialization..."+beanName+"=>"+bean);
return bean;
}
}
② BeanPostProcessor原理
AbstractAutowireCapableBeanFactory中关于bean和BeanPostProcessor执行次序由上到下
//给bean进行属性赋值
populateBean(beanName, mbd, instanceWrapper);
//然后调用initializeBean方法
Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//执行自定义初始化
invokeInitMethods(beanName, wrappedBean, mbd);
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
AbstractAutowireCapableBeanFactory.initializeBean源码如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//调用意识/通知方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用bean后置处理器的前置方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// //调用bean后置处理器的后置方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutowireCapableBeanFactory.invokeInitMethods方法源码如下:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
//调用InitializingBean.afterPropertiesSet
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//调用自定义初始化方法
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
【5】Spring底层使用BeanPostProcessor
Spring框架底层存在大量BeanPostProcessor,如下图:
示例一 :BeanValidationPostProcessor是处理bean校验
其Javadoc如下:
/**
* Simple {@link BeanPostProcessor} that checks JSR-303 constraint annotations
* in Spring-managed beans, throwing an initialization exception in case of
* constraint violations right before calling the bean's init method (if any).
*
* @author Juergen Hoeller
* @since 3.0
*/
public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean {
private Validator validator;
private boolean afterInitialization = false;
//...
}
示例二:ApplicationContextAwareProcessor帮助获取容器上下文
其Javadoc如下:
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
* implementation that passes the ApplicationContext to beans that
* implement the {@link EnvironmentAware}, {@link EmbeddedValueResolverAware},
* {@link ResourceLoaderAware}, {@link ApplicationEventPublisherAware},
* {@link MessageSourceAware} and/or {@link ApplicationContextAware} interfaces.
*
* Implemented interfaces are satisfied in order of their mention above.
*
*
Application contexts will automatically register this with their
* underlying bean factory. Applications do not use this directly.
*
* @author Juergen Hoeller
* @author Costin Leau
* @author Chris Beams
* @since 10.10.2003
* @see org.springframework.context.EnvironmentAware
* @see org.springframework.context.EmbeddedValueResolverAware
* @see org.springframework.context.ResourceLoaderAware
* @see org.springframework.context.ApplicationEventPublisherAware
* @see org.springframework.context.MessageSourceAware
* @see org.springframework.context.ApplicationContextAware
* @see org.springframework.context.support.AbstractApplicationContext#refresh()
*/
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
//...
}
如【3】中的dog类为例,其debug示意图如下:
【6】初始化和销毁方式测试
① 如果一个bean 综合应用下面六种种方式,执行顺序会怎样呢
Bean类如下:
public class Person implements InitializingBean,DisposableBean {
private String name;
private Integer age=1;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("Person(String name, Integer age) constructor"+this);
}
public Person() {
super();
System.out.println("Person() constructor"+age);
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 自定义init方法
public void init(){
System.out.println("-----Person.init()-----"+this);
}
// 自定义销毁方法
public void cleanUp(){
System.out.println("-----Person.cleanUp()-----"+this);
}
// InitializingBean的实现方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("-----InitializingBean.afterPropertiesSet()-----"+this);
}
//DisposableBean 的实现方法
@Override
public void destroy() throws Exception {
System.out.println("-----DisposableBean.destroy()-----"+this);
}
//对象创建并赋值之后调用
@PostConstruct
public void init2(){
System.out.println("-----@PostConstruct-----"+this);
}
//容器移除对象之前
@PreDestroy
public void destory2(){
System.out.println("-----@PreDestroy-----"+this);
}
}
配置类如下:
public class Person implements InitializingBean,DisposableBean {
private String name;
private Integer age=1;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("Person(String name, Integer age) constructor"+this);
}
public Person() {
super();
System.out.println("Person() constructor"+age);
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 自定义init方法
public void init(){
System.out.println("-----Person.init()-----"+this);
}
// 自定义销毁方法
public void cleanUp(){
System.out.println("-----Person.cleanUp()-----"+this);
}
// InitializingBean的实现方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("-----InitializingBean.afterPropertiesSet()-----"+this);
}
//DisposableBean 的实现方法
@Override
public void destroy() throws Exception {
System.out.println("-----DisposableBean.destroy()-----"+this);
}
//对象创建并赋值之后调用
@PostConstruct
public void init2(){
System.out.println("-----@PostConstruct-----"+this);
}
//容器移除对象之前
@PreDestroy
public void destory2(){
System.out.println("-----@PreDestroy-----"+this);
}
}
测试结果如下:
// 创建并初始化
Person(String name, Integer age) constructorPerson{name='lisi', age=20}
-----@PostConstruct-----Person{name='lisi', age=20}
-----InitializingBean.afterPropertiesSet()-----Person{name='lisi', age=20}
-----Person.init()-----Person{name='lisi', age=20}
//容器将要销毁
-----@PreDestroy-----Person{name='lisi', age=20}
-----DisposableBean.destroy()-----Person{name='lisi', age=20}
-----Person.cleanUp()-----Person{name='lisi', age=20}
即,最先使用bean的构造器为bean属性赋值,接着JSR250规范定义的两个注解,其次是InitializingBean和DisposableBean接口,最后才是我们自定义的初始化方法和销毁方法。注意,这里还没有引入BeanPostProcessor。
② 在①的基础上添加BeanPostProcessor
实例化bean并进行初始化
//调用构造方法
Person(String name, Integer age) constructorPerson{name='lisi', age=20}
//bean初始化前
BeanPostProcessor.postProcessBeforeInitialization...person=>Person{name='lisi', age=20}
//初始化操作
-----@PostConstruct-----Person{name='lisi', age=20}
-----InitializingBean.afterPropertiesSet()-----Person{name='lisi', age=20}
-----Person.init()-----Person{name='lisi', age=20}
//bean初始化后操作
BeanPostProcessor.postProcessAfterInitialization...person=>Person{name='lisi', age=20}
过程如下:类构造函数-->BeanPostProcessor-->@PostConstruct-->InitializingBean-->init()-->BeanPostProcessor
销毁bean
-----@PreDestroy-----Person{name='lisi', age=20}
-----DisposableBean.destroy()-----Person{name='lisi', age=20}
-----Person.cleanUp()-----Person{name='lisi', age=20}
完整图示如下(同颜色的说明相对应):
在调用bean的构造函数时会根据入参为bean属性赋值,如果入参为空则会给bean属性赋予默认值,引用类型为null,基本类型比如int为0。
【7】 @Autowired注解的值何时放入?
如下所示,redisTemplate这个依赖何时被容器注入到RedisController中?
通过上面分析可知,依赖注入是在@PostConstruct注解的方法调用前被完成的(在populateBean()方法中被注入
):
那么具体什么时候哪个类完成的 @Autowired注解注入依赖呢?
在类被实例化后由BeanPostProcessor完成的,哪个BeanPostProcessor?
具体是由AutowiredAnnotationBeanPostProcessor
完成的:
到此这篇关于Spring中bean的初始化和销毁几种实现方式详解的文章就介绍到这了,更多相关Spring中bean初始化和销毁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
你可能感兴趣的:(Spring中bean的初始化和销毁几种实现方式详解)
老榕树的Java专题:分享一个问题!!!
程序员_老榕树
树哥java专题:从0到1 java 开发语言
在实现类里定义了个全局静态变量:privatestaticSimpleDateFormat=newSimpleDateFormat("yyyy-MM-dd");然后在方法中使用sdf.parse(inputDto.getREQUESTDATE()).这样导致日期转换成莫名其妙的数据。首先,SimpleDateFormat的线程不安全问题:SimpleDateFormat不是线程安全的类。当多个线程
老榕树的Java专题:你了解java吗?
程序员_老榕树
树哥java专题:从0到1 java 开发语言
Java:编程世界的多面手在当今数字化浪潮汹涌澎湃的时代,编程技术无疑成为了驱动创新与变革的核心引擎。而在众多编程语言中,Java犹如一颗璀璨的明星,闪耀着独特而迷人的光芒,以其卓越的特性和广泛的应用场景,在全球范围内赢得了无数开发者的青睐与追捧。一、Java的诞生与发展历程Java的故事始于20世纪90年代初,由SunMicrosystems(现已被Oracle收购)的一群天才工程师精心打造。其
es6+函数语法规范(二):函数默认参数、判断函数参数个数、函数作用域、扩展运算符、箭头函数、es10函数扩展
m0_50134014
前端 javascript es6
文章目录一、默认参数二、判断函数参数个数三、属性与作用域3.1length属性3.2name属性3.3作用域四、扩展运算符4.1SpreadOperator把数组或伪数组展开成用逗号隔开的值4.2RestParameter用来解决函数参数不确定的场景五、箭头函数5.1箭头函数与普通函数5.2参数和返回值的讨论5.3箭头函数与普通函数中this的指向练习六、ES10扩展一、默认参数对于函数而言,经常
Day16 洛谷真题讲解
流星雨.又来临
c++ 算法 开发语言
呀呀呀呀,嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻,太开心了,终于看到了一丝丝快乐的光环,终于ac了大家先来看一眼这道题,我觉得其实还是真的蛮经典的,刚开始的时候我心思看看如何能够把每个数给他存进一个数组里面,后来我发现原来,这个题目,只要在深深的探查一下,就会慢慢发现其中的道理,于是我重新开始想方法,okl,终于找到了一个这个好个找规律,我真觉得这个普及-的题,好像每一道都有点找规律。大家仔细看我上面的那个演草纸
一站式3D虚拟展厅搭建方案,让企业展示更高效
jimumeta
虚拟展厅 3D 行业资讯 3d 3D展厅 虚拟展厅 数字人
在数字化浪潮中,众多企业倾向于采用线上3D虚拟展厅来展现其产品特色、环境风貌及企业实力。然而,构建一个高质量的3D虚拟展厅不仅要求专业的技术背景,还需投入大量的时间和人力资源。视创云展能够以低成本高效率地搭建3D虚拟展厅,通过整合虚拟数字人与虚拟场景,促进虚拟环境中的多人互动,营造出一种超沉浸式的“零距离”社交体验。丰富的3D展厅模板:视创云展平台汇聚了大量预设的3D展厅模板,用户只需简单拖拽和编
2025年AI编程的进展与突破
调皮的芋头
低代码 神经网络 人工智能 AIGC AI编程
2025年AI编程的进展与突破1.AI编程能力达到中级工程师水平核心技术突破:大语言模型(如GPT-4、Claude3.5)通过海量代码训练,已能理解自然语言需求并生成符合规范的代码,支持复杂任务(如多文件修改、测试生成、代码部署)。能力边界扩展:AI可独立完成模块化开发、代码调试及简单架构设计,例如Meta计划在2025年将中级工程师的工作自动化,部分企业代码生成率已超50%(如科大讯飞)。多模
KubeBlocks
喝醉酒的小白
K8s 学习
KubeBlocks笔记概述KubeBlocks是一个开源的Kubernetes数据库Operator,旨在帮助用户在Kubernetes上运行和管理多种类型的数据库。它提供了通用的API和命令行工具kbcli,支持MySQL、PostgreSQL、MongoDB、Redis、Kafka等多种数据库引擎。主要特点高可用性:集成成熟的高可用解决方案,如Orchestrator、Patroni和Sen
Hive JDBC 大数据查询场景下的 Socket 读超时问题及实战解决方案
窝窝和牛牛
大数据 hive hadoop
文章目录HiveJDBC大数据查询场景下的Socket读超时问题及实战解决方案问题背景️解决方案方案一:通过JDBCURL直接配置超时(推荐)方案二:动态设置全局loginTimeout(兼容旧版本)总结与建议HiveJDBC大数据查询场景下的Socket读超时问题及实战解决方案问题背景在使用HiveJDBC执行查询时,偶发SocketTimeoutException异常,堆栈显示在ResultS
iOS安全和逆向系列教程 第16篇:Frida入门与高级应用
自学不成才
iOS安全和逆向系列教程 cocoa macos objective-c
iOS逆向工程专栏第16篇:Frida入门与高级应用前言欢迎来到iOS逆向工程专栏的第16篇文章!在上一篇中,我们探讨了Cycript这一强大的逆向分析工具。今天,我们将深入学习功能更为强大、更为灵活的动态插桩工具——Frida。Frida作为现代iOS逆向工程中最受欢迎的工具之一,其强大的跨平台能力和灵活的JavaScript引擎使得我们能够轻松地分析和修改iOS应用的运行时行为。无论是逆向分析
iOS安全和逆向系列教程 第17篇:探讨ARM64架构与Swift逆向分析技术
自学不成才
iOS安全和逆向系列教程 ios 安全 架构
iOS安全和逆向系列教程第17篇:探讨ARM64架构与Swift逆向分析技术前言欢迎来到iOS安全和逆向系列教程的第17篇。在前面的文章中,我们已经学习了iOS逆向工程的基础知识,以及各种分析工具的使用方法。今天,我们将深入探讨ARM64架构以及Swift语言的逆向分析技术,这两者对于现代iOS应用的逆向工程至关重要。随着Apple全面迁移到ARM64架构和Swift语言的广泛应用,掌握这些技术已
【python】协程(coroutine)
atwdy
Python python coroutine 协程 asyncio
协程(coroutine)可以理解为一个可以中途暂停保存当前执行状态信息并可以从此处恢复执行的函数,多个协程共用一个线程执行,适合执行需要“等待”的任务。所以严格意义上,多个协程同一时刻也只有一个在真正的执行,因为线程是任务调度的基本单位。注意这里的执行指的是占用CPU计算,不包括等待阻塞等场景。python中实现协程的标准库是asyncio,标准库的实现中大致可以由底层到顶层分为下面几个对象:c
基于阿里云调用deepseek大模型
atwdy
大模型 deepseek deepseek-r1 deepseek API 阿里云
文章目录1.单轮对话2.多轮对话参考文档选择需要调用的模型,每个模型的详细信息中会有API示例(deepseek-r1),需要做的就是申请自己的APIkey就行了,过程中可能需要实名认证。python中安装OpenAISDK:pipinstallopenai。安装后如果出现ImportError,可能是python的版本低了,升级下版本。当前测试环境是Python3.9.7,openai==1.6
学习prompt
artificiali
prompt
1解释概念中文指令:请借助费曼学习法,以简单的语言解释[特定概念]是什么,并提供一个例子来说明它如何应用。Prompt:PleaseusetheFeynmanLearningTechniquetoexplain[specificconcept]insimplelanguage,andprovideanexampletoillustratehowitapplies.2帕累托法则帮你找到最重要、最具挑
百变背景:万相实验室AIGC电商图片可控生成技术
阿里妈妈技术
AIGC 人工智能
✍本文作者:云芑、因尘、岁星、也鹿1.背景随着AI生成内容(AIGC)技术如Diffusion的飞速进展,现如今,大家已能够轻易地使用StableDiffusion(SD)[1]等文生图的模型或工具,将心中所想仅凭语言描述(prompt)即转化为具体图像。基于此,我们不禁思考:是否有可能进一步发展该技术,允许用户通过描述来为商品定制特定背景,从而协助商家快速且轻松地打造理想的商品图像?例如,为一个
c语言实现:输入一个字符串,统计出这个字符串的字符个数
artificiali
c语言算法 c语言
最近开始学遇到的一个小问题先上代码:#include#includeintmain(){charstr[100];intcount=0,i;printf("请输入一个字符串:");gets(str);//遍历字符串每个字符,累加字符数for(i=0;str[i]!='\0';i++){count++;}printf("输入的字符串中共有%d个字符。\n",count);return0;}在以上代码
人工智能学习大纲
互联网搬砖老肖
AI 原力计划 工具使用 人工智能 学习
前言人工智能正以惊人的速度发展,其潜力既令人兴奋,也引人深思。它既可能为解决全球性问题带来希望,也可能带来前所未有的挑战。人工智能时代的到来已是不可逆转的趋势,科幻电影中的某些场景或许将成为现实。我对人工智能的研究越深入,就越能感受到它的强大力量。我所担忧的不仅仅是它对就业市场的冲击,更是它可能对人类社会结构带来的深远影响。未来,对人工智能的理解可能像今天对电脑操作的掌握一样重要。掌握人工智能技术
nvm-Windows 安装与使用教程
互联网搬砖老肖
Vue 工具使用 C#从入门到放弃 nvm vue
nvm-Windows安装与使用教程前言不同的项目运行时可能需要不同的node版本才可以运行,由于来回进行卸载不同版本的node比较麻烦;所以需要使用node工程多版本管理。本人在配置时,通过网络搜索教程,由于文章时间过老,或者文章的互相拷贝导致配置时出现许多小问题,但最后也是配置成功了,想写下此文章帮助小伙伴们排除错误,节省各位宝贵的时间,如有问题欢迎留言讨论~注意:安装nvm时不能安装任何no
STM32与C51简述
THIRT13N
嵌入式 编程语言 stm32
STM32与C51简述嵌入式开发心得1.关于C51与STM32的说明C51是最早一批进入中国市场的可开发操作的板子/芯片,在早期有着较好的发展方向学习浪潮,早期也有着发达的社区可供交流。随着电子科技的蓬勃发展,STM32逐渐走进了人们的视野。STM32下的几块开发板以其精准得控制,完美得性能,与时俱进的外接设备受到了无数开发者的青睐,至今仍在电子科技的基础产业中起着极其重要的作用,并且发达的社区提
证书在“精“不在“多“,项目经理该考的证其实就3种……
项目经理刘湖南
职场和发展
考证是许多项目经理自我提升的一种重要方式。然而,面对市面上琳琅满目的证书,大家难免会陷入“选择恐惧症”,不知道该考哪一本,毕竟证书在"精"而不在"多"。那么项目经理究竟应该集中精力考什么类型的证书呢?第一种:认可度高的一般来说,一本证书的认可度高,意味着它在项目管理领域的知名度和影响力都很不错。在彼此都不怎么了解的情况下,雇主、上司或者客户很可能通过是否持有某些证书来判断项目经理是否具有较高的综合
token 网络安全 请求密钥
Hacker_LaoYi
web安全 安全
接口的安全性主要围绕token、timestamp和sign三个机制展开设计,保证接口的数据不会被篡改和重复调用,下面具体来看:Token授权机制:用户使用用户名密码登录后服务器给客户端返回一个Token(通常是UUID),并将Token-UserId以键值对的形式存放在缓存服务器中。服务端接收到请求后进行Token验证,如果Token不存在,说明请求无效。Token是客户端访问服务端的凭证。时间
Es6中promise的解释用法以及何为同步异步、回调函数和回调地狱?
HHR_hr
es6 前端 ecmascript
一.什么是回调函数?1.含义★回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在特定事件或条件发生时被调用执行。2.回调函数在编程中扮演着重要的角色,主要用于以下场景:①事件处理:在图形用户界面(GUI)或其他事件驱动的应用程序中,回调函数常用于处理用户交互和事件触发。②异步编程:在异步编程中,回调函数用于在任务完成时通知调用方,而不必等待任务的完成,从而提高应用程序的响应性。③处理操作系
计算机网络篇:基础知识总结与基于长期主义的内容更新
YGGP
计算机网络 计算机网络
基础知识总结和MySQL类似,我同样花了一周左右的时间根据csview对计算机网络部分的八股文进行了整理,主要的内容包括:概述、TCP与UDP、IP、HTTP,其中我个人认为最重要的是TCP这部分的内容。在此做一篇目录索引,对应到每一篇文章:【每日八股】计算机网络篇(一):概述【每日八股】计算机网络篇(二):TCP和UDP【每日八股】计算机网络篇(三):IP【每日八股】计算机网络篇(四):HTTP
苹果企业签名的性价比
苹果企业签名分发
苹果企业签名
苹果企业签名(AppleEnterpriseDeveloperProgram)是苹果公司为企业开发者提供的一种应用分发方式,允许企业在不通过AppStore的情况下,直接向员工或特定用户分发内部应用。其性价比取决于具体需求和使用场景,以下从多个角度分析其优缺点及适用性:---###**一、企业签名的主要优势**1.**无需上架AppStore**-适合企业内部工具、测试版应用或定制化应用,避免审核
C语言【进阶篇】之结构体 —— 从基础声明到复杂应用的进阶之路
EnigmaCoder
C语言 c语言 开发语言 学习
目录前言✍️结构体类型的声明结构体定义结构的特殊声明结构的自引用结构体内存对齐对齐规则为什么存在内存对齐修改默认对齐数结构体传参结构体实现位段什么是位段位段的内存分配位段的跨平台问题位段的应用位段使用的注意事项总结前言大家好!我是EnigmaCoder。本文收录于我的专栏C,感谢您的支持!在C语言编程体系里,结构体是整合不同类型数据的重要工具,它能够将多个相关数据组合为一个有机整体,显著提升数据处
初识操作系统
曳渔
# JavaEE java-ee java
目录一、操作系统的认识1、常见的操作系统:2、操作系统的两个基本功能:二、进程1、什么是进程(Process):2、进程的组成:3、进程的并发和并行执行:三、总结:一、操作系统的认识操作系统是⼀组做计算机资源管理的软件的统称。1、常见的操作系统:目前常见的操作系统有Windows系列、Unix系列、Linux系列、OSX系列、Android系列、iOS系列、鸿蒙等。·Windows是常见的个人电脑
二分查找 -- ”单次\多次“搜索旋转数组
Vaiey22
算法 数据结构 二分查找 旋转数组 python
背景信息:'''整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0=nums[left]:#截至到[mid]都是升序,表明mid左半部分有序ifnums[left]index:{search_1(nums,target)}")多次搜索旋转数组---复用旋转点(pivot)K:#todo场景2:"多次搜索"deffindMinIndex(nums):
01计算机视觉学习计划
依旧阳光的老码农
计算机视觉 计算机视觉 人工智能
计算机视觉系统学习计划(3-6个月)本计划按照数学→编程→图像处理→机器学习→深度学习→3D视觉→项目实战的顺序,确保从基础到高级,结合理论和实践。第一阶段(第1-2个月):基础夯实✅目标:掌握数学基础、Python/C++编程、基本图像处理1️⃣数学基础(2周)每日2小时线性代数:矩阵运算、特征值分解(推荐《线性代数及其应用》)概率统计:高斯分布、贝叶斯定理微积分:偏导数、梯度下降傅里叶变换:图
aardio - 虚表 —— 两个虚表之间互相拖动交换数据
卢光庆
aardio aardio
插入到虚表末尾的方法:importwin.ui;importgodking.vlistEx;/*DSG{{*/mainForm=win.form(text="vlistEx-tableadapter";right=849;bottom=578;border="thin")mainForm.add(radiobutton={cls="radiobutton";text="移动";left=768;t
【Spring Boot 接入 MongoDB】
龙少9543
后端 spring boot mongodb 后端
【SpringBoot接入MongoDB】在SpringBoot项目中接入MongoDB是一个常见的需求,以下是详细的步骤和配置方法:1.添加依赖在pom.xml文件中添加SpringDataMongoDB的依赖。org.springframework.bootspring-boot-starter-data-mongodb如果你使用的是Gradle,可以添加以下内容:implementation
iOS安全和逆向系列教程 第13篇:iOS动态分析基础
自学不成才
iOS安全和逆向系列教程 ios cocoa macos
iOS逆向工程专栏第13篇:iOS动态分析基础引言在前面的文章中,我们详细探讨了iOS系统架构、逆向开发环境搭建、Mach-O文件格式分析,以及各种静态分析工具和技术。通过静态分析,我们可以了解应用的结构、类和方法定义,以及基本的控制流程。然而,静态分析也存在明显的局限性:我们无法观察应用的实际运行状态,难以分析加密算法的实现细节,也无法直接查看网络请求的完整内容。这就是为什么我们需要动态分析技术
LeetCode[位运算] - #137 Single Number II
Cwind
java Algorithm LeetCode 题解 位运算
原题链接:#137 Single Number II
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现三次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
与#136类似,都是考察位运算。不过出现两次的可以使用异或运算的特性 n XOR n = 0, n XOR 0 = n,即某一
《JavaScript语言精粹》笔记
aijuans
JavaScript
0、JavaScript的简单数据类型包括数字、字符创、布尔值(true/false)、null和undefined值,其它值都是对象。
1、JavaScript只有一个数字类型,它在内部被表示为64位的浮点数。没有分离出整数,所以1和1.0的值相同。
2、NaN是一个数值,表示一个不能产生正常结果的运算结果。NaN不等于任何值,包括它本身。可以用函数isNaN(number)检测NaN,但是
你应该更新的Java知识之常用程序库
Kai_Ge
java
在很多人眼中,Java 已经是一门垂垂老矣的语言,但并不妨碍 Java 世界依然在前进。如果你曾离开 Java,云游于其它世界,或是每日只在遗留代码中挣扎,或许是时候抬起头,看看老 Java 中的新东西。
Guava
Guava[gwɑ:və],一句话,只要你做Java项目,就应该用Guava(Github)。
guava 是 Google 出品的一套 Java 核心库,在我看来,它甚至应该
HttpClient
120153216
httpclient
/**
* 可以传对象的请求转发,对象已流形式放入HTTP中
*/
public static Object doPost(Map<String,Object> parmMap,String url)
{
Object object = null;
HttpClient hc = new HttpClient();
String fullURL
Django model字段类型清单
2002wmj
django
Django 通过 models 实现数据库的创建、修改、删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField:一个自动递增的整型字段,添加记录时它会自动增长。你通常不需要直接使用这个字段;如果你不指定主键的话,系统会自动添加一个主键字段到你的model。(参阅自动主键字段) BooleanField:布尔字段,管理工具里会自动将其描述为checkbox。 Cha
在SQLSERVER中查找消耗CPU最多的SQL
357029540
SQL Server
返回消耗CPU数目最多的10条语句
SELECT TOP 10
total_worker_time/execution_count AS avg_cpu_cost, plan_handle,
execution_count,
(SELECT SUBSTRING(text, statement_start_of
Myeclipse项目无法部署,Undefined exploded archive location
7454103
eclipse MyEclipse
做个备忘!
错误信息为:
Undefined exploded archive location
原因:
在工程转移过程中,导致工程的配置文件出错;
解决方法:
GMT时间格式转换
adminjun
GMT 时间转换
普通的时间转换问题我这里就不再罗嗦了,我想大家应该都会那种低级的转换问题吧,现在我向大家总结一下如何转换GMT时间格式,这种格式的转换方法网上还不是很多,所以有必要总结一下,也算给有需要的朋友一个小小的帮助啦。
1、可以使用
SimpleDateFormat SimpleDateFormat
EEE-三位星期
d-天
MMM-月
yyyy-四位年
Oracle数据库新装连接串问题
aijuans
oracle数据库
割接新装了数据库,客户端登陆无问题,apache/cgi-bin程序有问题,sqlnet.log日志如下:
Fatal NI connect error 12170.
VERSION INFORMATION: TNS for Linux: Version 10.2.0.4.0 - Product
回顾java数组复制
ayaoxinchao
java 数组
在写这篇文章之前,也看了一些别人写的,基本上都是大同小异。文章是对java数组复制基础知识的回顾,算是作为学习笔记,供以后自己翻阅。首先,简单想一下这个问题:为什么要复制数组?我的个人理解:在我们在利用一个数组时,在每一次使用,我们都希望它的值是初始值。这时我们就要对数组进行复制,以达到原始数组值的安全性。java数组复制大致分为3种方式:①for循环方式 ②clone方式 ③arrayCopy方
java web会话监听并使用spring注入
bewithme
Java Web
在java web应用中,当你想在建立会话或移除会话时,让系统做某些事情,比如说,统计在线用户,每当有用户登录时,或退出时,那么可以用下面这个监听器来监听。
import java.util.ArrayList;
import java.ut
NoSQL数据库之Redis数据库管理(Redis的常用命令及高级应用)
bijian1013
redis 数据库 NoSQL
一 .Redis常用命令
Redis提供了丰富的命令对数据库和各种数据库类型进行操作,这些命令可以在Linux终端使用。
a.键值相关命令
b.服务器相关命令
1.键值相关命令
&
java枚举序列化问题
bingyingao
java 枚举 序列化
对象在网络中传输离不开序列化和反序列化。而如果序列化的对象中有枚举值就要特别注意一些发布兼容问题:
1.加一个枚举值
新机器代码读分布式缓存中老对象,没有问题,不会抛异常。
老机器代码读分布式缓存中新对像,反序列化会中断,所以在所有机器发布完成之前要避免出现新对象,或者提前让老机器拥有新增枚举的jar。
2.删一个枚举值
新机器代码读分布式缓存中老对象,反序列
【Spark七十八】Spark Kyro序列化
bit1129
spark
当使用SparkContext的saveAsObjectFile方法将对象序列化到文件,以及通过objectFile方法将对象从文件反序列出来的时候,Spark默认使用Java的序列化以及反序列化机制,通常情况下,这种序列化机制是很低效的,Spark支持使用Kyro作为对象的序列化和反序列化机制,序列化的速度比java更快,但是使用Kyro时要注意,Kyro目前还是有些bug。
Spark
Hybridizing OO and Functional Design
bookjovi
erlang haskell
推荐博文:
Tell Above, and Ask Below - Hybridizing OO and Functional Design
文章中把OO和FP讲的深入透彻,里面把smalltalk和haskell作为典型的两种编程范式代表语言,此点本人极为同意,smalltalk可以说是最能体现OO设计的面向对象语言,smalltalk的作者Alan kay也是OO的最早先驱,
Java-Collections Framework学习与总结-HashMap
BrokenDreams
Collections
开发中常常会用到这样一种数据结构,根据一个关键字,找到所需的信息。这个过程有点像查字典,拿到一个key,去字典表中查找对应的value。Java1.0版本提供了这样的类java.util.Dictionary(抽象类),基本上支持字典表的操作。后来引入了Map接口,更好的描述的这种数据结构。
&nb
读《研磨设计模式》-代码笔记-职责链模式-Chain Of Responsibility
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
/**
* 业务逻辑:项目经理只能处理500以下的费用申请,部门经理是1000,总经理不设限。简单起见,只同意“Tom”的申请
* bylijinnan
*/
abstract class Handler {
/*
Android中启动外部程序
cherishLC
android
1、启动外部程序
引用自:
http://blog.csdn.net/linxcool/article/details/7692374
//方法一
Intent intent=new Intent();
//包名 包名+类名(全路径)
intent.setClassName("com.linxcool", "com.linxcool.PlaneActi
summary_keep_rate
coollyj
SUM
BEGIN
/*DECLARE minDate varchar(20) ;
DECLARE maxDate varchar(20) ;*/
DECLARE stkDate varchar(20) ;
DECLARE done int default -1;
/* 游标中 注册服务器地址 */
DE
hadoop hdfs 添加数据目录出错
daizj
hadoop hdfs 扩容
由于原来配置的hadoop data目录快要用满了,故准备修改配置文件增加数据目录,以便扩容,但由于疏忽,把core-site.xml, hdfs-site.xml配置文件dfs.datanode.data.dir 配置项增加了配置目录,但未创建实际目录,重启datanode服务时,报如下错误:
2014-11-18 08:51:39,128 WARN org.apache.hadoop.h
grep 目录级联查找
dongwei_6688
grep
在Mac或者Linux下使用grep进行文件内容查找时,如果给定的目标搜索路径是当前目录,那么它默认只搜索当前目录下的文件,而不会搜索其下面子目录中的文件内容,如果想级联搜索下级目录,需要使用一个“-r”参数:
grep -n -r "GET" .
上面的命令将会找出当前目录“.”及当前目录中所有下级目录
yii 修改模块使用的布局文件
dcj3sjt126com
yii layouts
方法一:yii模块默认使用系统当前的主题布局文件,如果在主配置文件中配置了主题比如: 'theme'=>'mythm', 那么yii的模块就使用 protected/themes/mythm/views/layouts 下的布局文件; 如果未配置主题,那么 yii的模块就使用 protected/views/layouts 下的布局文件, 总之默认不是使用自身目录 pr
设计模式之单例模式
come_for_dream
设计模式 单例模式 懒汉式饿汉式 双重检验锁失败 无序写入
今天该来的面试还没来,这个店估计不会来电话了,安静下来写写博客也不错,没事翻了翻小易哥的博客甚至与大牛们之间的差距,基础知识不扎实建起来的楼再高也只能是危楼罢了,陈下心回归基础把以前学过的东西总结一下。
*********************************
8、数组
豆豆咖啡
二维数组 数组 一维数组
一、概念
数组是同一种类型数据的集合。其实数组就是一个容器。
二、好处
可以自动给数组中的元素从0开始编号,方便操作这些元素
三、格式
//一维数组
1,元素类型[] 变量名 = new 元素类型[元素的个数]
int[] arr =
Decode Ways
hcx2013
decode
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, det
Spring4.1新特性——异步调度和事件机制的异常处理
jinnianshilongnian
spring 4.1
目录
Spring4.1新特性——综述
Spring4.1新特性——Spring核心部分及其他
Spring4.1新特性——Spring缓存框架增强
Spring4.1新特性——异步调用和事件机制的异常处理
Spring4.1新特性——数据库集成测试脚本初始化
Spring4.1新特性——Spring MVC增强
Spring4.1新特性——页面自动化测试框架Spring MVC T
squid3(高命中率)缓存服务器配置
liyonghui160com
系统:centos 5.x
需要的软件:squid-3.0.STABLE25.tar.gz
1.下载squid
wget http://www.squid-cache.org/Versions/v3/3.0/squid-3.0.STABLE25.tar.gz
tar zxf squid-3.0.STABLE25.tar.gz &&
避免Java应用中NullPointerException的技巧和最佳实践
pda158
java
1) 从已知的String对象中调用equals()和equalsIgnoreCase()方法,而非未知对象。 总是从已知的非空String对象中调用equals()方法。因为equals()方法是对称的,调用a.equals(b)和调用b.equals(a)是完全相同的,这也是为什么程序员对于对象a和b这么不上心。如果调用者是空指针,这种调用可能导致一个空指针异常
Object unk
如何在Swift语言中创建http请求
shoothao
http swift
概述:本文通过实例从同步和异步两种方式上回答了”如何在Swift语言中创建http请求“的问题。
如果你对Objective-C比较了解的话,对于如何创建http请求你一定驾轻就熟了,而新语言Swift与其相比只有语法上的区别。但是,对才接触到这个崭新平台的初学者来说,他们仍然想知道“如何在Swift语言中创建http请求?”。
在这里,我将作出一些建议来回答上述问题。常见的
Spring事务的传播方式
uule
spring事务
传播方式:
新建事务
required
required_new - 挂起当前
非事务方式运行
supports
&nbs