Spring-IOC部分
Spring-IOC部分
1.SpringBean的配置详解(Bean标签)
(1)scope
默认情况下,单纯的Spring环境Bean的作用范围有两个:Singleton和Prototype
singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。生成的Bean不会存在单例池中
(2)lazy-init
当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可,本质上该Bean还是单例的
(3)init-method
可以在Bean中创建一个成员方法init,在Bean被实例化之后执行,或者实现InitializingBean 接口重写afterPropertiesSet方法
(4)Bean实例化配置
1.构造方式实例化:底层通过构造方法对Bean进行实例化
-
无参构造
-
有参构造
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"><constructor-arg name="name" value="haohao"/> </bean>
2.工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化
-
静态工厂方法实例化Bean
静态工厂方法实例化Bean,其实就是定义一个工厂类,提供一个静态方法用于生产Bean实例,在将该工厂类及其静态方法配置给Spring即可
//工厂类 public class UserDaoFactoryBean {//非静态工厂方法public static UserDao getUserDao(String name){//可以在此编写一些其他逻辑代码return new UserDaoImpl();} }
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean" factory-method="getUserDao"><constructor-arg name="name" value="haohao"/> </bean>
- 静态工厂方法是一个普通的静态方法,它负责创建并返回一个对象实例。
- 静态工厂方法本身不会被 Spring 容器管理,因为它是一个静态方法,不属于任何 Spring Bean。
-
实例工厂方法实例化Bean
<!-- 配置实例工厂Bean --> <bean id="userDaoFactoryBean2" class="com.itheima.factory.UserDaoFactoryBean2"/> <!-- 配置实例工厂Bean的哪个方法作为工厂方法 --> <bean id="userDao" factory-bean="userDaoFactoryBean2" factory-method="getUserDao"><constructor-arg name="name" value="haohao"/> </bean>
-
实现FactoryBean规范延迟实例化Bean
public interface FactoryBean<T> {String OBJECT_TYPE_ATTRIBUTE = “factoryBeanObjectType”;T getObject() throws Exception; //获得实例对象方法Class<?> getObjectType(); //获得实例对象类型方法default boolean isSingleton() {return true;} }
public class UserDaoFactoryBean3 implements FactoryBean<UserDao> {public UserDao getObject() throws Exception {return new UserDaoImpl();}public Class<?> getObjectType() {return UserDao.class;} }
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean3"/>
Spring容器创建时,FactoryBean被实例化了,并存储到了单例池singletonObjects中,但是getObject() 方法尚未被执行,UserDaoImpl也没被实例化,当首次用到UserDaoImpl时,才调用getObject() ,此工厂方式产生的Bean实例不会存储到单例池singletonObjects中,会存储到 factoryBeanObjectCache 缓存池中,并且后期每次使用到userDao都从该缓存池中返回的是同一个userDao实例。
(5)Bean的依赖注入配置
构造器方法注入就和使用有参构造器实例化Bean的方式一样
自动装配
如果被注入的属性类型是Bean引用的话,那么可以在 标签中使用 autowire 属性去配置自动注入方式,属性值有两个:
byName:通过属性名自动装配,即去匹配 setXxx 与 id=“xxx”(name=“xxx”)是否一致;
byType:通过Bean的类型从容器中匹配,匹配出多个相同Bean类型时,报错。
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" autowire="byType">
基于注解的依赖注入
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.username}")
public void setUsername(String username){
System.out.println(username);
}//使用在属性上直接注入
@Autowired
private UserDao userDao;
//使用在方法上直接注入
@Autowired
public void setUserDao(UserDao userDao){
System.out.println(userDao);
}@Autowired
@Qualifier("userDao2")
private UserDao userDao;//@Resource注解既可以根据类型注入,也可以根据名称注入,无参就是根据类型注入,有参数就是根据名称注入 是javax包下
@Resource
private UserDao userDao;
@Resource(name = "userDao2")
public void setUserDao(UserDao userDao){
System.out.println(userDao);
}
(6)Spring其他的配置标签
Spring 的 xml 标签大体上分为两类,一种是默认标签,一种是自定义标签
-
默认标签:就是不用额外导入其他命名空间约束的标签,例如 标签.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
-
自定义标签:就是需要额外引入其他命名空间约束,并通过前缀引用的标签,例如 context:property-placeholder/ 标签
在使用注解开发中,使用@Component注解代替标签,其他标签就可以定义一个配置类来替代原有的xml配置文件
@Configuration注解标识的类为配置类,替代原有xml配置文件,该注解第一个作用是标识该类是一个配置类,第二个作用是具备@Component作用
@ComponentScan 组件扫描配置,替代原有xml文件中的<context:component-scan base-package=“”/>
@PropertySource 注解用于加载外部properties资源配置,替代原有xml中的<context:property placeholder location=“”/>配置
@Import 用于加载其他配置类,替代原有xml中的配置
(7)基于注解配置
除了使用xml进行配置,还可以使用注解配置,在Bean类上使用注解@Component注解,value属性指定当前Bean实例的beanName,也可以省略不写,不写的情况下为当前类名首字母小写。
需要在xml文件中进行配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/xmlSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 告知Spring框架去itheima包及其子包下去扫描使用了注解的类 --><context:component-scan base-package="com.itheima"/>
</beans>
//获取方式:applicationContext.getBean("userDao");
@Component("userDao")
public class UserDaoImpl implements UserDao {
}
//获取方式:applicationContext.getBean("userDaoImpl");
@Component
public class UserDaoImpl implements UserDao {
}
xml配置和注解的对应
为了每层Bean标识的注解语义化更加明确,@Component又衍生出如下三个注解
(8)Spring配置其他注解
@Primary注解用于标注相同类型的Bean优先被使用权,@Primary 是Spring3.0引入的,与@Component和@Bean一起使用,标注该Bean的优先级更高,则在通过类型获取Bean或通过@Autowired根据类型进行注入时,会选用优先级更高的
注解 @Profile 标注在类或方法上,标注当前产生的Bean从属于哪个环境,只有激活了当前环境,被标注的Bean才能被注册到Spring容器里,不指定环境的Bean,任何环境下都能注册到Spring容器里
2.Spring的get方法
3.Spring配置非自定义Bean(第三方提供的Bean)
配置非自定义的Bean需要考虑如下两个问题:
- 被配置的Bean的实例化方式是什么?无参构造、有参构造、静态工厂方式还是实例工厂方式;
- 被配置的Bean是否需要注入必要属性。
以MyBatis为例
原始代码
//加载mybatis核心配置文件,使用Spring静态工厂方式
InputStream in = Resources.getResourceAsStream(“mybatis-conifg.xml”);
//创建SqlSessionFactoryBuilder对象,使用Spring无参构造方式
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//调用SqlSessionFactoryBuilder的build方法,使用Spring实例工厂方式
SqlSessionFactory sqlSessionFactory = builder.build(in);
用xml配置
<!--静态工厂方式产生Bean实例-->
<bean id=“inputStream” class=“org.apache.ibatis.io.Resources” factory-method=“getResourceAsStream”><constructor-arg name=“resource” value=“mybatis-config.xml/>
</bean>
<!--无参构造方式产生Bean实例-->
<bean id="sqlSessionFactoryBuilder" class="org.apache.ibatis.session.SqlSessionFactoryBuilder"/>
<!--实例工厂方式产生Bean实例-->
<bean id="sqlSessionFactory" factory-bean="sqlSessionFactoryBuilder" factory-method="build"><constructor-arg name="inputStream" ref="inputStream"/>
</bean>
用注解配置
//将方法返回值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;
}
工厂方法所在类必须要被Spring管理
如果需要注入参数的话,@Autowired可以省略
@Bean
@Autowired //根据类型匹配参数
public Object objectDemo01(UserDao userDao){System.out.println(userDao);return new Object();
}
@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.Bean实例化的基本流程
Spring容器在进行初始化时,会将xml配置的的信息封装成一个BeanDefinition对象,所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects的Map集合中,当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。
5.Spring的后处理器
Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用。Spring主要有两种后处理器:
-
BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;
BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器(xml文件中用bean配置)管理的话,那么Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。
public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory); }
可以动态修改BeanDefinition(修改class,修改初始化方法,是否懒加载)
Spring 提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作
public class MyBeanFactoryPostProcessor2 implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {BeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.itheima.dao.UserDaoImpl2");beanDefinitionRegistry.registerBeanDefinition("userDao2",beanDefinition);} }
这个对象本身也会交给spring容器管理,进入到单例池中
-
BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行。
Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程,例如:属性的填充、初始方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理
public interface BeanPostProcessor {@Nullable//在属性注入完毕,init初始化方法执行之前被回调default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Nullable//在初始化方法执行之后,被添加到单例池singletonObjects之前被回调default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;} }
这个对象本身也会交给spring容器管理,进入到单例池中
6.Spring的生命周期
Spring Bean的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段:
- Bean的实例化阶段:Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化;
- Bean的初始化阶段:Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充、执行一些Aware接口方法、执行BeanPostProcessor方法、执行InitializingBean接口的初始化方法、执行自定义初始化init方法等。该阶段是Spring最具技术含量和复杂度的阶段,Aop增强功能,后面要学习的Spring的注解功能等、spring高频面试题Bean的循环引用问题都是在这个阶段体现的;
- Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObjects中去了,即完成了Spring Bean的整个生命周期。
初始化阶段主要设计以下几个过程:
- Bean实例的属性填充
- Aware接口属性注入
- BeanPostProcessor的before()方法回调
- InitializingBean接口的初始化方法回调
- 自定义初始化方法init回调
- BeanPostProcessor的after()方法回调
(1)Bean的实例属性填充
Spring在进行属性注入时,会分为如下几种情况:
-
注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;
-
注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
-
注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)问题,下面会详细阐述解决方案
三级缓存
public class DefaultSingletonBeanRegistry ... {//1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存"Map<String, Object> singletonObjects = new ConcurrentHashMap(256);//2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存"Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);//3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三级缓存"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,存储到一级缓存,删除二三级缓存。
(2)Aware接口
Aware接口是一种框架辅助属性注入的一种思想,其他框架中也可以看到类似的接口。框架具备高度封装性,我们接触到的一般都是业务代码,一个底层功能API不能轻易的获取到,但是这不意味着永远用不到这些对象,如果用到了,就可以使用框架提供的类似Aware的接口,让框架给我们注入该对象。
7.整合第三方框架(如何使用第三方功能)
(1)使用默认命名空间 beans
Spring整合MyBatis的步骤如下:
原始代码
public static void main(String[] args) throws IOException {// 加载 MyBatis 配置文件String resource = "com/example/config/mybatis-config.xml";Reader reader = Resources.getResourceAsReader(resource);// 构建 SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);// 打开 SqlSessiontry (SqlSession session = sqlSessionFactory.openSession()) {// 获取 MapperUserMapper userMapper = session.getMapper(UserMapper.class);// 查询用户User user = userMapper.selectUserById(1);System.out.println("User: " + user.getUsername() + ", Password: " + user.getPassword());// 插入用户User newUser = new User();newUser.setUsername("newuser");newUser.setPassword("newpassword");userMapper.insertUser(newUser);session.commit(); // 提交事务}}
-
导入MyBatis整合Spring的相关坐标;
-
编写Mapper和Mapper.xml;
-
配置SqlSessionFactoryBean和MapperScannerConfigurer;
<!--配置数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="jdbc:mysql://localhost:3306/mybatis"></property><property name="username" value="root"></property><property name="password" value="root"></property> </bean> <!--配置SqlSessionFactoryBean--> <bean class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"></property> </bean> <!--配置Mapper包扫描--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.itheima.dao"></property> </bean>
-
编写测试代码
原理(对照原始代码看)
-
SqlSessionFactoryBean:实现了FactoryBean规范,用于提供SqlSessionFactory;用于创建SqlSession
-
MapperScannerConfigurer:实现了BeanDefinitionRegistryPostProcessor接口,完成注册,用于扫描指定包下的mapper注册到BeanDefinitionMap中;
-
MapperFactoryBean:实现了FactoryBean规范,它的getObject方法就是this.getSqlSession().getMapper(this.mapperInterface);
-
ClassPathMapperScanner:在mapper(接口,无法实例化成一个对象)注册到BeanDefinitionMap后,动态修改BeanDefinitionMap,对于每一个mapper的class修改成MapperFactoryBean
definition.setAutowireMode(2) 修改了自动注入状态(根据类型),所以MapperFactoryBean中的setSqlSessionFactory会自动注入进去。
使用注解整合
@Configuration
@ComponentScan("com.itheima")
@MapperScan("com.itheima.mapper")
public class ApplicationContextConfig {@Beanpublic DataSource dataSource(){DruidDataSource dataSource = new DruidDataSource();//省略部分代码return dataSource;}@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean;
}}
@MapperScan不是Spring提供的注解,是MyBatis为了整合Spring,在整合包org.mybatis.spring.annotation中提供的注解。这个注解上有一个元注解,@Import({MapperScannerRegistrar.class}),当@MapperScan被扫描加载时,会解析@Import注解,从而加载指定的类,此处就是加载了MapperScannerRegistrar。
MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,Spring会自动调用registerBeanDefinitions方法,该方法中又注册MapperScannerConfigurer类,而MapperScannerConfigurer类作用是扫描Mapper,向容器中注册Mapper对应的MapperFactoryBean
@Import注解
@Import可以导入如下三种类:
-
普通的配置类
-
实现ImportSelector接口的类
重写String[] selectImports(AnnotationMetadata annotationMetadata)方法,//返回要进行注册的Bean的全限定名数组
-
实现ImportBeanDefinitionRegistrar接口的类
重写registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry),手动注册BeanDefinition
(2)使用第三方命名空间(如何生效的)
需求:加载外部properties文件,将键值对存储在Spring容器中
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
引入context命名空间,在使用context命名空间的标签,使用SpEL表达式在xml或注解中根据key获得value
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:jdbc.properties" /><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean>
<beans>
-
将自定义标签的约束 与 物理约束文件与网络约束名称的约束 以键值对形式存储到一个spring.schemas文件里,该文件存储在类加载路径的 META-INF里,Spring会自动加载到;
http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd
在xsd文件中就定义了命令空间下有哪些子标签
-
将自定义命名空间的名称 与 自定义命名空间的处理器映射关系 以键值对形式存在到一个叫spring.handlers文件里,该文件存储在类加载路径的 META-INF里,Spring会自动加载到;
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
-
在ContextNamespaceHandler中,会为命名空间中的每一个标签都注册一个解析器
public class ContextNamespaceHandler extends NamespaceHandlerSupport {public ContextNamespaceHandler() {}public void init() {this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());this.registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());this.registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());this.registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());this.registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());this.registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());this.registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());} }
根据标签,找到对应的解析器进行解析
8.Spring注解的解析原理
(1)xml配置组件扫描
<context:component-scan base-package="com.itheima"/>
component-scan是一个context命名空间下的自定义标签,所以要找到对应的命名空间处理器NamespaceHandler 和 解析器.
将ComponentScanBeanDefinitionParser进行了注册
(2)配置类配置组件扫描
@Configuration
@ComponentScan("com.itheima")
public class AppConfig {
}
使用AnnotationConfigApplicationContext容器在进行创建时,内部调用了如下代码,该工具注册了几个Bean后处理器
相关文章:
Spring-IOC部分
Spring-IOC部分 1.SpringBean的配置详解(Bean标签) (1)scope 默认情况下,单纯的Spring环境Bean的作用范围有两个:Singleton和Prototype singleton:单例,默认值,Spring…...
使用GitHub Actions构建CI/CD流程
GitHub Actions 简介 GitHub Actions 是一种自动化软件开发工作流的方式,与 GitHub.com 深度集成。开发人员可以通过配置 GitHub Actions 来实现基于事件触发的自动工作流,比如,当有任意用户向 master 分支提交代码时,自动执行一…...
Ubuntu服务器 无法正常启动redis
当我们在阿里云服务器上启动redis服务 运行下述命令时 service redis-server start 会出现如下报错 Failed to start redis-server.service: Unit redis-server.service not found. 如图: 解决方案: 通过以下命令重新安装Redis: sudo apt…...
MySQL 索引原理
一、索引基础概念 1. 索引是什么? 定义:索引是帮助MySQL高效获取数据的有序数据结构,类似书籍的目录。核心作用:减少磁盘I/O次数,提升查询速度(以空间换时间)。 2. 索引的优缺点 优点缺点加…...
前端快速入门学习3——CSS介绍与选择器
1.概述 CSS全名是cascading style sheets,中文名层叠样式表。 用于定义网页样式和布局的样式表语言。 通过 CSS,你可以指定页面中各个元素的颜色、字体、大小、间距、边框、背景等样式,从而实现更精确的页面设计。 HTML与CSS的关系:HTML相当…...
WPF 免费UI 控件HandyControl
示例效果和代码 直接可以用 Button 按钮 | HandyOrg 1.安装 , 输入 HandyControl 2.<!--配置HandyControl--> <!--配置HandyControl--> <ResourceDictionary Source"pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/> …...
【代码艺廊】pyside6桌面应用范例:homemade-toolset
在研发测试日常工作中,通常会遇到很多琐碎的事情,占用我们工作的时间和精力,从而导致我们不能把大部分的注意力放在主要的工作上面。为了解决这个问题,除了加人之外,我们通常会开发一些日常用的效率工具,比…...
Hive 常见面试 300 问
一、Hive 基础概念 什么是 Hive?它的主要用途是什么? Hive 与传统关系型数据库有什么区别? 简述 Hive 的架构,各个组件的作用是什么? 解释 Hive 中的元数据,它存储在哪里? Hive 支持哪些数据格式?各自的特点是什么? 什么是 Hive 表的分区?为什么要使用分区? 什么是 …...
OpenMinus 源码深度解析:从 React 模式到多智能体架构实现
OpenMinus 源码深度解析:从 React 模式到多智能体架构实现 本文基于 2024 年 3 月 9 日最新代码版本解析,完整代码已上传至 GitHub(附项目地址https://github.com/mannaandpoem/OpenManus) 一、项目背景与核心价值 1.1 项目定位 …...
【Linux网络与网络编程】04.TCP Socket编程
一、TCP Socket编程接口 // 创建套接字 int socket(int domain, int type, int protocol); // 参数: // domain:域(协议家族),这里使用 AF_INET 表示进行网络编程 // type:网络通信传输的类型࿰…...
初识数据结构——算法效率的“两面性”:时间与空间复杂度全解析
📊 算法效率的“两面性”:时间与空间复杂度全解析 1️⃣ 如何衡量算法好坏? 举个栗子🌰:斐波那契数列的递归实现 public static long Fib(int N) {if(N < 3) return 1;return Fib(N-1) Fib(N-2); }问题…...
CCF GESP C++编程 八级认证真题 2025年3月
C 八级 2025 年 03 月 题号 1 2 3 4 5 6 7 8 答案 B C B A D D D 一、单选题 第 1 题 国家“以旧换新”政策仍在继续,小杨家决定在家里旧的冰箱、电视、洗衣机、微波炉中选两种换新。其中,冰箱有4种型号可选,电视有6种型号可选,…...
React: hook相当于函数吗?
一、Hook 是一个函数,但不仅仅是函数 函数的本质 Hook 确实是一个 JavaScript 函数,例如 useState、useEffect 或自定义 Hook 都是函数。它们可以接受参数(如初始状态值或依赖项数组),并返回结果(如状态值和…...
Git 从入门到精通(开源协作特别版)
🧠 Git 从入门到精通(开源协作特别版) ✅ 基础命令 🧰 高级用法 🛠️ 开源实战技巧 🌍 GitHub 社区协作 适合:从0开始 → 熟练开发者 → 参与/维护开源项目 🔰 第1章:…...
《探索边缘计算:重塑未来智能物联网的关键技术》
最近研学过程中发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…...
什么是缓存穿透、缓存雪崩、缓存击穿?
什么是缓存? 缓存就是数据交换的缓冲区,是存贮数据的临时地方,一般读写性能较高。 怎么防止缓存穿透? 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到…...
洛谷题单3-P4956 [COCI 2017 2018 #6] Davor-python-流程图重构
题目描述 在征服南极之后,Davor 开始了一项新的挑战。下一步是在西伯利亚、格林兰、挪威的北极圈远征。 他将在 2018 年 12 月 31 日开始出发,在这之前需要一共筹集 n 元钱。 他打算在每个星期一筹集 x 元,星期二筹集 xk 元,……...
解决浏览器报错Mixed Content
前端代码写死了访问后端的请求为:http://service.xxx.com:8080/api/,前端代码中混合内容(Mixed Content) 导致的。浏览器使用https访问站点时,这个请求会被拦截,并且浏览器打印 login.vue:151 Mixed Conten…...
HCIP【BGP协议(详解)】
目录 1 BGP协议产生背景 2 BGP协议特性 2.1 自治系统间路由传播 2.2 路由矢量协议 2.3 防环机制 2.4 基于TCP传输 2.5 路由更新机制 2.6 丰富的路由属性 2.7 支持CIDR和路由聚合 2.8 路由过滤和策略控制 2.9 动态对等体功能 3 BGP基本术语 4 BGP规划问题 4.1 路…...
集合与容器:List、HashMap(II)
一、ArrayList 是集合框架中最核心的动态数组实现,高频使用的容器之一。 1. 核心数据结构 基于数组实现,维护elementData数组存储元素: transient修饰的elementData不会被默认序列化(通过自定义序列化逻辑优化存储)…...
mac 安装MySQL
1、打开官网,点击Downloads 2、在downloads页面选择MySQL Community Server 3、选择对应的设备和版本,点击下载 4、下载选择 5、下载完成后,点击安装 6、next 到Configguration 时要输入密码(千万别忘记) 7.最后输…...
Pascal语言的软件开发工具
使用Pascal语言的软件开发工具 引言 随着计算机科学的发展,编程语言层出不穷,程序员们在开发时可以选择多种多样的工具。而Pascal语言作为一种历史悠久的程序设计语言,尽管在当今编程语言的生态中已不再是主流,但其优雅的语法和…...
vue组件开发:什么是VUE组件?
什么是VUE组件 在我们实际开发过程中你也许会发现有很多代码是重复的,它们可能是一个按钮、一个表单、一个列表等等,其中最为显著的应该是列表。 以CSDN的首页为例: 上述截图中的文章列表可能会在多处出现,比如此截图是精选博客…...
如何在Springboot的Mapper中轻松添加新的SQL语句呀?
在如今的软件开发界,Spring Boot可是非常受欢迎的框架哦,尤其是在微服务和RESTful API的构建上,真的是让人爱不释手!今天,我们就来聊聊如何为Spring Boot项目中的Mapper添加新的SQL语句吧!说起来࿰…...
微服务架构: SpringCloud服务注册与发现详解
# 微服务架构: SpringCloud服务注册与发现详解 一、什么是微服务架构 微服务架构简介 微服务架构(Microservices Architecture)是一种以一组小型服务应用程序构建系统的软件架构风格。每个服务运行在自己的进程中,通过精简的HTTP API进行通信…...
现代简约杂志海报包装网页设计无衬线英文字体安装包 Seriusans – Condensed Sans Display Font
Seriusans 是一种 Condensed Sans Display 字体,将现代简约与大胆融为一体。其狭窄而醒目的字体营造出强大的存在感,使其成为有影响力设计的绝佳选择,例如海报、杂志标题、品牌、包装、网页设计、运动图形、社论布局、广告活动、企业演示&…...
C/C++的条件编译
一、什么是条件编译? 条件编译是指在编译阶段根据某些条件来决定是否编译某段代码。这通常通过预处理指令来实现,比如 #if、#ifdef、#ifndef、#else、#elif 和 #endif。 二、为什么使用条件编译? 跨平台开发:不同的操作…...
视野,,地面覆盖,重叠需求,FPS,飞行速度等的计算公式
一、计算相机视野与重叠需求 1. 相机参数 IDS UI-5280CP: 分辨率:2456x2054 像素。传感器:假设为 1/1.8" CMOS(常见型号),尺寸约 6.78 mm(宽) 5.67 mm(高…...
ARXML文件解析-1
目录 1 摘要2 ARXML文件2.1 作用及典型应用场景2.2 **ARXML文件的结构树**2.3 TAG(XML元素)2.4 ARXML文件关键元素解析2.4.1 XML声明与处理指令2.4.2 XML注释2.4.3 ADMIN-DATA元素2.4.3 语言相关元素2.4.5 AR-PACKAGE体系结构2.4.6. 数据转换框架2.4.7 S…...
传统开发者视角:智能合约与区块链数据库探秘
前言 在上一篇文章:探秘区块链开发:智能合约在 DApp 中的地位及与传统开发差异中我为大家从传统开发者的角度讲解了一下什么是智能合约。 简单的来说智能合约对于传统前端开发者可以说是API接口,而后端开发者则可以说是负责接口逻辑的程序。 然而从传统的开发意识跳跃到D…...
游戏引擎学习第204天
回顾并为今天的内容做铺垫 好,现在开始这一集。今天我们将进行一些用户界面编程,觉得这是一个展示如何编写这类代码的好时机。很多人对如何做用户界面代码都很好奇,所以展示一下如何编写是非常有意义的。 我之所以在现在的这个地方做这些工…...
蓝桥杯2024年第十五届省赛真题-R 格式
题目链接: 思路: 通过数组模拟d的每一位,逐位进行计算,从而实现对d的精确处理。 代码: #include<bits/stdc.h> #define int long long using namespace std; const int N 2020;int n; string s; vector<i…...
Haskell语言的区块链安全
Haskell语言在区块链安全中的应用 引言 随着区块链技术的发展,它已经成为金融、供应链管理、身份认证等多个领域的重要基础设施。然而,区块链的安全性问题一直是行业关注的焦点。为了确保区块链的安全性,开发者需要选择合适的编程语言来编写…...
BUUCTF-web刷题篇(11)
20.admin 这道题很可能用admin或者伪造admin进行登录,用admin进行登录,随便填写密码进不去,发现页面有register、login,用admin注册提示已经被注册。 方法一:(burp爆破) 进入登陆界面&#x…...
TensorFlow
TensorFlow 是一个由 Google 开发并开源的机器学习和深度学习库,被广泛应用于各类机器学习项目。以下为你详细介绍: 概述 TensorFlow 最初是为了满足 Google 内部大规模机器学习需求而研发,后于 2015 年开源。它提供了一个强大且灵活的生态…...
分子生成的深层次层次变分自编码器 - DrugHIVE 测评
一、背景介绍 DrugHIVE 来源于南加州大学定量与计算生物学系的 Remo Rohs 为通讯作者的文章:《Structure-Based Drug Design with a Deep Hierarchical Generative Model》。文章链接:https://pubs.acs.org/doi/10.1021/acs.jcim.4c01193。该文章在 202…...
54.大学生心理健康管理系统(基于springboot项目)
目录 1.系统的受众说明 2.相关技术 2.1 B/S结构 2.2 MySQL数据库 3.系统分析 3.1可行性分析 3.1.1时间可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.1.4 技术可行性 3.1.5 法律可行性 3.2系统流程分析 3.3系统功能需求分析 3.4 系统非功能需求分析 4.系统设计…...
Linux文件特殊权限管理及进程和线程
acl 权限优先级 拥有者 > 特殊指定用户 > 权限多的组 >权限少的组 > 其他 mask阈值 mask是能够赋予指定用户权限的最大阀值 当设定完毕文件的acl列表之后用chmod缩小了文件拥有组的权力 mask会发生变化 恢复: setfacl -m m: 权限 :rwx 文件/…...
Vue2+Vue3 45-90集学习笔记
Vue2Vue3 45-90集学习笔记 小兔鲜首页 页面开发思路: 分析页面,按模块拆分组件,搭架子(局部注册或全局注册) 局部注册:App.js中 导入(import),注册(compon…...
【Web 服务器】的工作原理
🌐 Web 服务器的工作原理 Web 服务器的主要作用是 接收客户端请求(通常是浏览器发出的 HTTP/HTTPS 请求),处理请求,并返回相应的数据(如网页、图片、API 响应等)。 📌 工作流程 1️…...
LeetCode 5 -- 区间DP | 中心拓展算法
题目描述 最长回文子串 数据规模为 5e5,必须 manacher 算法 1. DP 由于 r e v e r s e ( ) reverse() reverse() 的时间复杂度是 O ( N ) O(N) O(N),因此暴力肯定是不行的。 d p dp dp 的思路:如果 s [ l . . r ] s[l..r] s[l..r] 是一个…...
IntelliJ IDEA中Spring Boot 3.4.x+集成Redis 7.x:最新配置与实战指南
前言 Spring Boot 3.4.x作为当前最新稳定版本,全面支持Java 17与Jakarta EE 10规范。本文以Spring Boot 3.4.1和Redis 7.x为例,详解如何在IDEA中快速接入Redis,涵盖最新依赖配置、数据序列化优化、缓存注解及高…...
数仓建模中计算累计销量
在数仓建模中计算累计销量,通常需要结合时间维度和业务逻辑设计合理的模型与计算逻辑。以下是分步骤的实现思路和示例: 1. 模型设计 累计销量的计算通常基于星型模型或雪花模型,核心结构包括: 事实表:记录每一笔销售…...
(多看) CExercise_05_1函数_1.2计算base的exponent次幂
题目: 键盘录入两个整数:底(base)和幂指数(exponent),计算base的exponent次幂,并打印输出对应的结果。(注意底和幂指数都可能是负数) 提示:求幂运算时,基础的思路就是先无脑把指数转…...
Pollard‘s Rho 算法
Pollard’s Rho 算法:一场数学与计算机科学的巧妙结合 在现代计算机科学中,素数分解、整数因子化问题有着广泛的应用,尤其是在密码学领域。然而,当面对一个大合数时,寻找其因子仍然是一个非常复杂的问题。我们常常依赖…...
8款分形长虹玻璃科幻渐变海报设计JPG背景素材 The Gradient Backgrounds Pack
天空从未如此美好 — 直到有人将日落洒在您的屏幕上。这些渐变是带有心跳的液体颜色,从熔化的金色转变为深紫色,就像地平线一样。 8 个背景中的每一个都以 45003000 像素和 300dpi 的速度脉冲,清晰到足以让您感觉自己可以直接踏入光芒中。但这…...
AIGC9——AIGC时代的用户体验革命:智能交互与隐私保护的平衡术
引言:当AI成为交互主角 2024年,淘宝AI客服"阿里小蜜"日均处理20亿次咨询,日本虚拟偶像"初音未来"演唱会门票3秒售罄——这些现象标志着AIGC已深度融入人机交互场景。但与此同时,过度个性化的推荐引发"信…...
vm虚拟机虚拟出网卡并ping通外网
在 Linux 和 Windows 系统中,即使不使用网络命名空间(namespace),也能实现虚拟网卡上网。以下是不同场景下的实现方法: 一、Linux 系统(不使用网络命名空间) 1. 直接创建虚拟网卡对(…...
基于时间卷积网络TCN实现电力负荷多变量时序预测(PyTorch版)
前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对…...
ESXi8的部署过程
目录 一、系统安装 二、ESXI8的序列号 三、挂载硬盘和新建VMFS数据分区 四、通过数据存储浏览器上传下载文件 五、Windows远程桌面端口隐射 六、导出虚机 一、系统安装 1、使用UtrIOS系统制作ESXI8的启动盘; 2、服务器启动F8按键进入Popup启动选项,选择U盘启动; 3、安…...