spring bean

图灵课堂学习笔记

1. BeanFactory与ApplicationContext的关系

p56

  1. ApplicationContext在BeanFactory基础上对功能进行了扩展,例如:监听功能、国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装;
  2. beanFactory容器对象:提供对于bean基本操作能力。查找bean 存储bean。
  3. applicationContext不仅继承了Beanfactory,而且还维护了beanfactory的引用。
  4. bean 的初始化时间不一样。BeanFactory 是首次调用getBean()时才进行Bean 的创建。Application 是在配置文件加载,容器一创建Bean就实例化初始化好了。

1.1 beanfactory 和 application 继承体系

BeanFactory 实现->DefaultListableBreanFactory
ApplicationContext

1.2 bean 范围 初始化

  • @scope
    • signleton、prototype

1.3 初始化 实现 InitializingBean

  • InitializingBean初始化
    afterPropertiesSet() 在属性注入之后执行。 类似于在注入dao后,再执行
  • DisposableBean 销毁
    destroy()

除此之外,我们还可以通过实现 InitializingBean 接口,完成一些Bean的初始化操作,如下:

构造方法、注解postConstruct,实现InitializingBean方法afterPropertiesSet,bean初始化init方法执行顺序。
通过启动日志我们可以看出执行顺序优先级:构造方法 > postConstruct >afterPropertiesSet > init方法。

@Component
public class MyInitializingBean implements InitializingBean {

    public MyInitializingBean() {
        System.out.println("我是MyInitializingBean构造方法执行...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("我是afterPropertiesSet方法执行...");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("我是postConstruct方法执行...");
    }

    public void init(){
        System.out.println("我是init方法执行...");
    }

    @Bean(initMethod = "init")
    public MyInitializingBean test() {
        return new MyInitializingBean();
    }
}

3

1.4 实例化bean 方式 factoryBean

  • 静态工厂方法实例化Bean
  • 实例工厂方法实例化Bean
  • 实现FactoryBean规范延迟实例化Bean

public class MyFactoryBean implements FactoryBean<User> {
    /**
     * 返回bean
     *
     * @return
     * @throws Exception
     */
    @Override
    public User getObject() throws Exception {
        User user = new User();
        user.setId(1L);
        user.setName("zhangsan");
        return user;
    }
    /**
     * 返回bean 的类型 class
     *
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

1.5 spring的get 方法

Spring 的get方法
3

// 根据 beanName 获取容器中的 Bean 实例,需要手动强转
UserService userService = (UserService) applicationContext
	.getBean("userService");
// 根据 Bean 类型去容器中匹配对应的 Bean 实例,如存在多个匹配 Bean 则报错
UserService userService2 = applicationContext
	.getBean(UserService.class);
// 根据 beanName 获取容器中的 Bean 实例,指定 Bean 的 Type 类型
UserService userService3 = applicationContext
	.getBean("userService",
UserService.class);

2.Bean 实例化的基本流

ioc p119
singletonObjects 单例池

  • beanfactory :
    • signletonObjects 单例池
    • beandifinitionMap bean定义集合

简化说:

  • 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;
  • 将BeanDefinition存储在一个名为beanDefinitionMap的Map<String,BeanDefinition>中;
  • ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象;
  • 创建好的Bean实例对象,被存储到一个名为singletonObjects的Map<String,Object>中;
  • 当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回。

BeanDefinition

Spring容器在进行初始化时,会将xml配置的<bean>的信息封装成一个BeanDefinition对象,所有的BeanDefinition存储到一个名beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects的Map集合中当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回

3

beandifiniton:保存了bean的信息,比如beanclass,是否单例,是否懒加载。

2.1 spring 的后处理器

以达到动态注册BeanDefinition动态修改BeanDefinition以及动态修改Bean的作用。Spring主要有两种后处理器:
⚫ BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕Bean实例化之前执行; 执行一次
⚫ BeanPostProcessor:Bean后处理器,一般在Bean实例化之后填充到单例池singletonObjects之前执行。每个bean 实例化后都执行一次。

2.1.1 bean工厂的后置处理器 BeanFactoryPostProcessor

Bean工厂后处理器 – BeanFactoryPostProcessor
可以注册beandefinition
BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。

@Component
public class MyBeanFactoryPostProcessor  implements BeanFactoryPostProcessor {
    /**
     * @param beanFactory  BeanFactory的子接口  其实是 DefaultListableBeanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //动态注册BeanDefinition 是个接口  使用RootBeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.hyp.pojo.User");
//        rootBeanDefinition.setBeanClass(User.class);
        // 没有注册到beanDefinitionmap中的方法
        //通过beanFactory 强转 DefaultListableBeanFactory   
        DefaultListableBeanFactory defaultListableBeanFactory=
                (DefaultListableBeanFactory) beanFactory;
        //注入注册到beanDefinitionmap中
        defaultListableBeanFactory.registerBeanDefinition("user001",rootBeanDefinition);
    }
}

2.1.2 专门注册beandefinition 的bean工厂后置处理器

提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作

@Component
public class MyBeanDefinitionRegistyPostProcessor implements BeanDefinitionRegistryPostProcessor {
    /**
     * 本类实现,用来快速注册beandefinition 的方法
     * @param registry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //动态注册BeanDefinition 是个接口  使用RootBeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.hyp.pojo.User");
//        rootBeanDefinition.setBeanClass(User.class);
        registry.registerBeanDefinition("user001",rootBeanDefinition);
        System.out.println("先被调用");
    }

    /**
     * BeanFactoryPostProcessor 的方法
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("后被调用");
    }
}

3

2.2 bean 的后置处理器

Bean后处理器 – BeanPostProcessor
每个类都调用一次

Bean被实例化后,到最终缓存到名为singletonObjects单例池之前中间会经过Bean的初始化过程,例如:属性的填充初始方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理。跟上面的Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor,会在流程节点上被Spring自动调用

3

2.3 bean 的生命周期

p145
Spring Bean的生命周期是从 Bean 实例化之后(反射创建对象),即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段:

  • Bean的实例化阶段

Spring框架会取出BeanDefinition的信息进行判断(各种if的判断)当前Bean的范围是否是singleton的是否不是延迟加载的是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化;

  • Bean的初始化阶段:·

Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充执行一些Aware接口方法执行BeanPostProcessor方法执行InitializingBean接口的初始化方法执行自定义初始化init方法等。该阶段是Spring最具技术含量和复杂度的阶段,Aop增强功能,后面要学习的Spring的注解功能等、spring高频面试题Bean的循环引用问题都是在这个阶段体现的;

  • Bean的完成阶段

经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池 singletonObjects中去了,即完成了Spring Bean的整个生命周期。

2.3.1 生命周期步骤

  • bean 的属性填充
  • Aware接口的属性注入 如果自己实现aware接口,spring会注入属性
  • BeanPostProcessor before() 方法
  • @PostConstruct() 方法
  • InitializingBean 接口的初始化方法
  • 自定义初始化方法 回调 initMethod=“”
  • BeanPostProcessor after() 方法调用

2.3.2 属性填充

BeanDefinition 中有对当前Bean实体的注入信息通过属性propertyValues进行了存储,

3

属性注入的三种情况。

  • 注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;
  • 注入单向对象引用属性时,(user类需要注入userDao类,userDao容器中没有)从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
  • 注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)问题

循环依赖问题

3
3

解决

	// 1.一级缓存 单例池map 最终存储完整bean成品的容器 初始化和实例化都完成的bean
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	//2.二级缓存 bean 不是完整的bean 还没有完全初始化
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

	// 3.单例 Bean 的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建 Bean ,称之为 " 三级缓存
	//半成品bean 包装一个ObjectFactory 未被别人引用,创建对象就注入进去。
	// UserDao通过第三级缓存获取到了对象(user) 将该对象(user) 注入到获取UserDao中,把user从第三级缓存移除,user注入到第二级缓存中。
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);


UserService和UserDao循环依赖的过程结合上述三级缓存描述一下
⚫ UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存;
⚫ UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao;
⚫ UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
⚫ UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移入二级缓存;
⚫ UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存;
⚫ UserService 注入UserDao;
⚫ UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存。

3

2.3.3 aware 接口

Aware接口回调方法作用
ServletContextAwaresetServletContext(ServletContext context)Spring框架回调方法注入ServletContext对象,web环境下才生效
BeanFactoryAwaresetBeanFactory(BeanFactory factory)Spring框架回调方法注入beanFactory对象
BeanNameAwaresetBeanName(String beanName)Spring框架回调方法注入当前Bean在容器中的beanName
ApplicationContextAwaresetApplicationContext(ApplicationContext applicationContext)Spring框架回调方法注入applicationContext对象

2.3 ioc 整体流程

3

3 整合mybatis

  • 配置SqlSessionFactoryBean
    作用 将sqlSessionFactory 存储到spring 容器中

  • MapperScannerConfigurer
    作用 扫描指定包,产生mapper对象存储到spring 容器

3.1 原理

P166
Spring整合MyBatis的原理剖析
整合包里提供了·一个SqlSessionFactoryBean一个扫描Mapper的配置对象,SqlSessionFactoryBean一旦被实例化,就开始扫描Mapper并通过动态代理产生Mapper的实现类存储到Spring容器中。相关的有如下四个类:

  1. SqlSessionFactoryBean:需要进行配置,用于提供SqlSessionFactory;
  • 解释
    配置SqlSessionFactoryBean作用是向容器中提供SqlSessionFactory,SqlSessionFactoryBean实现了FactoryBeanInitializingBean两个接口,所以会自动执行getObject() 和afterPropertiesSet()方法
SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean{
public void afterPropertiesSet() throws Exception {
// 创建 SqlSessionFactory 对象
this.sqlSessionFactory = this.buildSqlSessionFactory();
}
public SqlSessionFactory getObject() throws Exception {
return this.sqlSessionFactory;
}
}
  1. MapperScannerConfigurer:需要进行配置,用于扫描指定mapper注册BeanDefinition;

配置MapperScannerConfigurer作用是扫描Mapper,向容器中注册Mapper对应的MapperFactoryBean,MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessorInitializingBean两个接口,会在postProcessBeanDefinitionRegistry方法中向容器中注册MapperFactoryBean

  1. MapperFactoryBean:Mapper的FactoryBean,获得指定Mapper时调用getObject方法;
  2. ClassPathMapperScanner:definition.setAutowireMode(2) 修改了自动注入状态,所以MapperFactoryBean中的setSqlSessionFactory会自动注入进去。

PS:autowireMode取值:1是根据名称自动装配,2是根据类型自动装配

4.注解

4.1 注解依赖注入

xml配置 注解 描述

注解描述
@Scope在类上或使用了@Bean标注的方法上,标注Bean的作用范围,取值为singleton或prototype
@Lazy在类上或使用了@Bean标注的方法上,标注Bean是否延迟加载,取值为true和false
@PostConstruct在方法上使用,标注Bean的实例化后执行的方法
@PreDestroy在方法上使用,标注Bean的销毁前执行方法

容器中有多个Userdao 可以注入List
3

3

属性注入注解描述
@Value使用在字段或方法上,用于注入普通数据
@Autowired使用在字段或方法上,用于根据类型(byType)注入引用数据 ·默认通过byType方式注入
@Qualifier使用在字段或方法上,结合@Autowired,根据名称注入
@Resource使用在字段或方法上,根据类型或名称进行注入 默认通过byName方式注入

//通过@Value 注入properties文件中的属性

@Value("haohao")
private String username;
@Value("haohao")
public void setUsername(String username){
System.out.println(username);
}


@Value("${jdbc.username}")
private String username;
@Value("${jdbc.username}")
public void setUsername(String username){
System.out.println(username);
}


4.2 非自定义bean注解开发

非自定义Bean不能像自定义Bean一样使用@Component进行管理,非自定义Bean要通过工厂的方式进行实例化,使用@Bean标注方法即可,@Bean的属性为beanName,如不指定为当前工厂方法名称

// 将方法返回值 Bean 实例以 @Bean 注解指定的名称存储到 Spring 容器中
@Bean("dataSource")
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}

// 使用@Qualifier 根据名称进行Bean的匹配;
// 使用@Value 根据名称进行普通数据类型匹配。
@Bean
public Object objectDemo02(@Qualifier("userDao") UserDao userDao,
@Value("${jdbc.username}") String username){
System.out.println(userDao);
System.out.println(username);
return new Object();
}

4.3 Spring 配置类开发

@Configuration 注解标识的类为配置类,替代原有xml配置文件,
该注解第一个作用是标识该类是一个配置类
第二个作用是具备@Component作用

@PropertySource 注解用于加载外部properties资源配置,替代原有xml中的 <context:property-
placeholder location=“”/> 配置

@Import 用于加载其他配置类

@import使用:

  • ①直接编写到@Import中,并且id值 是全类名
  • ②自定义ImportSelector接口的实现类,通过selectimports方法实现(方法的返回值 就是要纳入IoC容器的Bean) 。 并且 告知程序 自己编写的实现类。
    @Import({Orange.class,MyImportSelector.class})
  • ③编写ImportBeanDefinitionRegistrar接口的实现类,重写方法
    @Import({Orange.class,MyImportSelector.class,ImportBeanDefinitionRegistrar.class})
@PropertySource({"classpath:jdbc.properties","classpath:xxx.properties"})
@Configuration
@ComponentScan("com.hyp")
public class SpringConfiguration {

}

4.3.1 import的使用 原理链接

链接@Import 学习使用

  1. 普通导入Bean.class
@Import(value = {User.class})
public class SpringConfiguration {}
  1. importSelector
public class MyImportSelector  implements ImportSelector {
	/**
	 * 为什么要使用ImportSelector?
	 * ImportSelector在SpringBoot中大量被使用,
	 * 各种@EnableXXX注解表示开启XXX,这些注解基本上都是使用了@Import注解导入一个ImportSelector。
	 * 比如需要开启Eureka,开启Nacos,只需要简单的一行注解就能搞定。
	 * @param importingClassMetadata
	 * @return
	 */
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		//数组中放入需要引入spring中的类名
		return new String[]{Test.class.getName()};
	}
}

然后创建一个自定义注解 @EnableTest:

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MySelector.class)//引入MySelector.class
public @interface EnableTest {
}


最后创建一个App用来测试:

@EnableTest//这里加上EnableTest注解
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(App.class);

        System.out.println(ac.getBean(Test.class));//测试是否能够从容器中获取到外部的Test的对象。
    }
}

测试结果肯定是能够获取到的!

为什么要使用ImportSelector?
ImportSelector在SpringBoot中大量被使用,各种@EnableXXX注解表示开启XXX,这些注解基本上都是使用了@Import注解导入一个ImportSelector。
比如需要开启Eureka,开启Nacos,只需要简单的一行注解就能搞定。

  1. ImportBeanDefinitionRegistrar

4.4 注解解析原理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JVM OOM问题排查与解决思路

OOM原因 1. 堆溢出 报错信息&#xff1a; java.lang.OutOfMemoryError: Java heap space 代码中可能存在大对象分配&#xff0c;无法获得足够的内存分配 可能发生内存泄露&#xff0c;导致内存被无效占用以至于耗尽 2. 永久代/元空间溢出 报错信息&#xff1a; java.lang.O…

C#,码海拾贝(19)——一般实矩阵的QR分解(QR Decomposition)方法之C#源代码,《C#数值计算算法编程》源代码升级改进版

1 实矩阵 实矩阵&#xff0c;指的是矩阵中所有的数都是实数的矩阵。如果一个矩阵中含有除实数以外的数&#xff0c;那么这个矩阵就不是实矩阵。 2 QR&#xff08;正交三角&#xff09;分解法 QR&#xff08;正交三角&#xff09;分解法是求一般矩阵全部特征值的最有效并广泛应…

Flowable从入门到源码分析

什么是工作流&#xff1f; 工作流&#xff0c;是把业务之间的各个步骤以及规则进行抽象和概括性的描述。使用特定的语言为业务流程建模&#xff0c;让其运行在计算机上&#xff0c;并让计算机进行计算和推动。 工作流解决的痛点在于&#xff0c;解除业务宏观流程和微观逻辑的…

jenkins gitlab asp.net core持续集成

什么是jenkins Jenkins直接取自其官方文档&#xff0c;是一个独立的开源自动化服务器&#xff0c;您可以使用它来自动执行与构建、测试、交付或部署软件相关的各种任务。 jenkins可以干什么 Jenkins 通过自动执行某些脚本来生成部署所需的文件来工作。这些脚本称为JenkinsFi…

2023_深入学习HTML5

H5 基于html5和 css3和一部分JS API 结合的开发平台(环境) 语义化标签 header : 表示头部&#xff0c;块级元素 footer &#xff1a; 表示底部&#xff0c;块级元素 section &#xff1a;区块 nav &#xff1a; 表示导航链接 aside &#xff1a; 表示侧边栏 output &am…

二叉搜索树(BSTree)

目录 一、二叉搜索树 二、二叉搜索树的接口及实现 1、二叉搜索树的查找 2、二叉搜索树的插入 3、二叉搜索树的删除 三、二叉搜索树的递归版本 本期博客主要分享二叉搜索树的底层实现。(主要是笔记&#xff0c;供自己复习使用&#x1f602;) 一、二叉搜索树 二叉搜索树(B…

MybatisPlus主键策略

Mybatis默认主键策略是TableId(type IdType.ASSIGN_ID) 这是默认策略雪花算法 此时主键类型可以是String 数据表字段类型可以是bigint int varchar 无需数据表主键自增 TableId(type IdType.ASSIGN_AUTO) 是主键自增策略:该策略为跟随数据库表的主键递增策略&…

一致性框架设计方案

补充组件依赖 前言 对于供应链业务&#xff0c;一般对数据一致性要求高。且由于业务复杂&#xff0c;可能会存在一个业务功能触发几个异步操作的场景&#xff0c;且要保证相关操作同时触发或不触发。 为了降低技术设计难度、代码编写难度&#xff0c;特意设计最终一致性框架&a…

ChatGPT+Ai绘图【stable-diffusion实战】

ai绘图 stable-diffusion生成【还有很大的提升空间】 提示词1 Picture a planet where every living thing is made of light. The landscapes are breathtakingly beautiful, with mountains and waterfalls made of swirling patterns of color. What kind of societies m…

程序员跳槽,要求涨薪50%过分吗?

如果问在TI行业涨工资最快的方式是什么&#xff1f; 回答最多的一定是&#xff1a;跳槽&#xff01; 前段时间&#xff0c;知乎上这样一条帖子引发了不少IT圈子的朋友的讨论 &#xff0c;有网友提问 “程序员跳槽要求涨薪50%过分吗&#xff1f;” 截图来源于知乎&#xff0c;…

摄影知识整理

目录 焦距 焦距分类 对焦 相机的MF与AF 自动对焦操作 自动对焦方式 镜头防抖 防抖模式 景深 景深的作用 影响景深的因素 景深预览 摄影三大元素 光圈 光圈的作用 光圈与景深的关系 感光度&#xff08;ISO) 注意 感光度的作用 快门 B门与T门 快门速度 闪…

【SSM】SpringMVC(三:SpringMVC拦截器)

文章目录 1. 登录案例2. 拦截器2.1 应用2.2 拦截器的执行原理2.3 拦截器执行的时机2.4 拦截器的实现方法2.5 拦截器的实现步骤2.6 开发拦截器 1. 登录案例 【login.jsp】 <%--Created by IntelliJ IDEA.User: BeyongDate: 2023/4/17Time: 11:43To change this template use…

SQL的函数

文章目录 一、SQL LCASE() 函数二、SQL MID() 函数三、SQL LEN() 函数四、SQL ROUND() 函数五、SQL NOW() 函数六、SQL FORMAT() 函数总结 一、SQL LCASE() 函数 LCASE() 函数把字段的值转换为小写。 SQL LCASE() 语法 SELECT LCASE(column_name) FROM table_name;用于 SQL …

入行IC选择国企、私企还是外企?(内附各IC大厂薪资福利情况)

不少人想要转行IC&#xff0c;但不知道该如何选择公司&#xff1f;下面就来为大家盘点一下IC大厂的薪资和工作情况&#xff0c;欢迎大家在评论区补充。 一&#xff0e;老 牌 巨 头 在 IC 设计领域深耕许久&#xff0c;流程完善、技术扎实&#xff0c;公司各项制度都很完善、前…

IT知识百科:什么是暴力破解?

暴力破解是一种常见的网络安全攻击方法&#xff0c;它利用计算机程序自动尝试大量的密码组合来破解密码。这种攻击方法通常用于获取未经授权的访问权限&#xff0c;如入侵网络系统或个人账户。在本文中&#xff0c;我们将探讨暴力破解的原理、工具和防范方法。 暴力破解的原理 …

TCP/UDP协议 (详解)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

Linux搭建SVN服务器详细教程

前言 本文讲解 Linux 系统下如何搭建 SVN 服务器&#xff0c;详细说明各配置项的功能&#xff0c;最终实现可管控多个项目的复杂配置。 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统&#xff0c;通过采用分支管理系统的高效管理&#xff0c;实现最终集…

HANA SDA连接外部数据库到BW的步骤

咱都知道&#xff0c;我们不能直接从BW连接到外部数据库。第一步得从HANA database通过SDA去建一个到外部DB的连接。 数据库连接好了&#xff0c;那么接下来别忘了&#xff0c;还得建一个源系统。 也就是说第一步&#xff0c;我们要用HANA SDA通过Linux ODBC driver去连接外部…

PHP快速入门05-时间日期与时区,附30个常用案例

文章目录 前言一、时间日期与时区1.1 时间与日期1.2 时区 二、 30个日期时间函数的用法示例2.1 获取当前的时间戳2.2 将时间戳格式化为日期时间2.3 获取当前的日期2.4 获取当前的时间2.5 获取当前年份2.6 获取当前月份2.7 获取当前日期的第几天2.8 计算两个日期之间的天数差2.9…

【生活工作经验 十】ChatGPT模型对话初探

最近探索了下全球大火的ChatGPT&#xff0c;想对此做个初步了解 一篇博客 当今社会&#xff0c;自然语言处理技术得到了迅速的发展&#xff0c;人工智能技术也越来越受到关注。其中&#xff0c;基于深度学习的大型语言模型&#xff0c;如GPT&#xff08;Generative Pre-train…