Spring | 基础

news2025/7/20 13:12:05

1. IOC和DI

IOC:控制反转,其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源。而应用了 IOC 之后,则是**容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。**这种行为也被称为查找的被动形式。

DI:依赖注入,IOC的另一种表述方式,即**组件以一些预先定义好的方式(setter方法)**接受来自容器的资源注入。

图解
可见,有了IOC容器之后,对象的创建都是在容器中进行,用户所要做的只是从容器中获取已经创建好的对象而已


2. 配置Bean

2.1 Bean 的配置方法

2.1.1 在 xml 文件中通过全类名(反射)来配置 Bean

<bean id="helloWorld2" class="edu.just.spring.beans.HelloWorld"></bean>

class: bean 的全类名, 通过反射的方式在 IOC 容器中创建 Bean, 所以要求 Bean 中必须有无参的构造器
id: 标识容器中的 bean. id 唯一.


2.1.2 在 xml 中通过静态工厂方法来配置 Bean
调用静态工厂方法创建 Bean 是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节

创建 Bean 实例

public class Car {

	private String brand;
	private String corp;
	private double price;
	
	public Car(String brand, String corp, double price) {
		this.brand = brand;
		this.corp = corp;
		this.price = price;
	}

}
/**
 * 静态工厂方法: 只要调用某一个类的静态方法就可以返回 Bean 的实例
 */
public class StaticCarFactory {

	private static Map<String, Car> cars = new HashMap<>();
	
	static {
		cars.put("audi", new Car("audi", "xixi", 2000));
		cars.put("ford", new Car("ford", "hello", 401111));
	}
	
	public static Car getCar(String name) {
		return cars.get(name);
	}
	
}

配置 Bean:
class 属性:指向静态工厂方法的全类名
factory-method:指向静态工厂方法的名字
constructor-arg:如果工厂方法需要传入参数, 则用 constructor-arg 来配置参数

<bean id="car1" class="edu.just.spring.beans.factory.StaticCarFactory" factory-method="getCar">
	<constructor-arg value="audi"></constructor-arg>
</bean>

结果:

Car [brand=audi, corp=xixi, price=2000.0]

2.1.3 在 xml 中通过实例工厂方法配置 Bean
将对象的创建过程封装到另一个对象实例的方法中,当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关系对象的创建细节

/**
 * 实例工厂方法: 实例工厂的方法, 即需要创建工厂本身, 在调用工厂的实例方法来返回 bean 的实例
 */
public class InstanceCarFactory {

	private Map<String, Car> cars = null;
	
	public InstanceCarFactory() {
		cars = new HashMap<>();
		cars.put("audi", new Car("audi", "xixi", 20000));
		cars.put("ford", new Car("ford", "hha", 30000));
	}
	
	public Car getCar(String name) {
		return cars.get(name);
	}
}

配置 Bean:
factory-bean :指向实例工厂方法的 Bean
factory-method :指向实例工厂方法的名字
constructor-arg:如果工厂方法需要传入参数, 则用 constructor-arg 来配置参数

<!-- 配置工厂的实例 -->
<bean id="carFactory" class="edu.just.spring.beans.factory.InstanceCarFactory"></bean>

<bean id="car2" factory-bean="carFactory" factory-method="getCar">
	<constructor-arg value="ford"></constructor-arg>
</bean>

结果:

Car [brand=ford, corp=hha, price=30000.0]

2.1.4 实现 FactoryBean 接口配置 Bean

  • Spring 中有两种类型的 Bean,一种是普通 Bean,另一种是工厂 Bean,即 FactoryBean
  • 工厂 Bean 跟普通 Bean 不同,其返回的对象不是指定类的一个实例,而是该工厂 Bean 的 getObject 方法所返回的对象
//自定义的 FactoryBean 需要实现 FactoryBean 接口
public class CarFactoryBean implements FactoryBean<Car>{
	
	private String brand;
	
	public void setBrand(String brand) {
		this.brand = brand;
	}
	
	//返回 Bean 的对象
	@Override
	public Car getObject() throws Exception {
		return new Car(brand, 500000);
	}

	//返回 Bean 的类型
	@Override
	public Class<?> getObjectType() {
		return Car.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}
}

配置 Bean:
通过 FactoryBean 来配置 Bean 的实例
class:指向 FactoryBean 的全类名
property:配置 FactoryBean 的属性

但实际返回的实例却是 FactoryBean 的 getObject() 方法返回的实例

<bean id="carFactoryBean" class="edu.just.spring.beans.FactoryBean.CarFactoryBean">
	<property name="brand" value="audi"></property>
</bean>

结果:

Car [brand=audi, price=500000.0]

**2.1.5 基于注解的方式来配置 Bean** * [Spring | 基于注解配置Bean(一)](https://www.jianshu.com/p/46ddc6812295) * [Spring | 基于注解配置Bean(二)](https://www.jianshu.com/p/e0e780629c82)

2.2 ApplicationContext

在Spring IOC 容器读取 Bean 配置创建 Bean 实例之前,必须对它进行实例化。只有在容器实例化之后,才可以从 IOC 容器里获取 Bean 实例并使用。Spring 提供了两种类型的 IOC 容器实现

  • BeanFactory:IOC 容器的基本实现
  • ApplicationContext:提供了更多的高级特性,是 BeanFactory 的子接口

BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身
ApplicationContext 面向使用 Spring 框架的开发者,几乎所有应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

public class Main {
	public static void main(String[] args) {
		//1. 创建 Spring 得 IOC 容器对象
		//ApplicationContext 代笔 IOC 容器
		//ClassPathXmlApplicationContext: 是 ApplicationContext 接口的实现类, 该实现类从类路径下来加载配置文件.
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//2. 对 IOC 容器中获取 Bean 实例
		//利用 id 定位到 IOC 容器中的 bean
		HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld2");
	
		//利用类型返回 IOC 容器中的 Bean, 但要求 IOC 容器中必须只能有一个该类型的 Bean
//		HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
		System.out.println(helloWorld);
	
//		//3. 调用方法
//		helloWorld.hello();
	}
}

2.3 依赖注入的方式

**属性注入:**即通过 setter 方法注入 Bean 的属性值或依赖的对象。属性注入是实际应用中最常用的注入方式

<bean id="helloWorld2" class="edu.just.spring.beans.HelloWorld">
	<property name="name" value="Spring"></property>
</bean>

**构造器注入:**通过构造方法注入 Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化之后就可以使用。构造器注入在 `` 元素里面声明属性,`` 中没有 name 属性 ``` ```

2.4 注入属性值细节

字面值: 可用字符串表示的值,可以通过 <value>200</value> 元素标签或 value="nihao" 属性进行注入。
PS: 若字面值中包含特殊字符,可以使用 <![CDATA[]]>把字面值包裹

引用其他 Bean: 在 Bean 的配置文件中,可以通过 <ref> 元素或者 ref 属性为 Bean 的属性或者构造器参数指定对 Bean 的引用

<bean id="car1" class="edu.just.spring.beans.Car"></bean>

<bean id="person" class="edu.just.spring.beans.Person">
	<property name="name" value="Tom"></property>
	<property name="age" value="25"></property>
	<!-- 可以使用 property 的 ref 属性建立 bean 之间的引用关系 -->
	<property name="car" ref="car1"></property>
	
	<!-- 通过 ref 属性添加引用 -->
	<property name="car">
		<ref bean="car1"/>
	</property>
	
	<!-- 内部 Bean, 不能被外部引用, 只能在内部使用 -->
	<property name="car">
		<bean class="edu.just.spring.beans.Car">
			<constructor-arg value="Ford"></constructor-arg>
			<constructor-arg value="Changan"></constructor-arg>
			<constructor-arg value="200000"></constructor-arg>
		</bean>
	</property>
</bean>

内部 Bean: 内部 Bean 声明直接包含在 <poperty> 或者 <constructor-arg> 元素里,不需要设置任何 id 或 name 属性。同时内部 Bean 不能使用在其他任何地方

集合属性: 在 Spring 中可以通过一组内置的 xml 标签,如 <list><set><map>

  • list 标签
<!-- 测试如何配置集合属性 -->
<bean id="person3" class="edu.just.spring.beans.collections.Person">
	<property name="name" value="Mike"></property>
	<property name="age" value="20"></property>
	<property name="cars">
		<!-- 使用 list 节点为 List 类型的属性赋值 -->
		<list>
			<ref bean="car1"/>
			<ref bean="car2"/>
			<!-- 可以指定内部 Bean -->
			<bean class="edu.just.spring.beans.Car">
				<constructor-arg value="Ford"></constructor-arg>
				<constructor-arg value="Changan"></constructor-arg>
				<constructor-arg value="200000"></constructor-arg>
			</bean>
		</list>
	</property>
</bean>
  • map 标签
<!-- 配置 Map 属性值 -->
<bean id="newPerson" class="edu.just.spring.beans.collections.Person2">
	<property name="name" value="Rose"></property>
	<property name="age" value="29"></property>
	<property name="cars">
		<!-- 使用 map 节点 的 entry 子节点配置 Map 类型的成员变量 -->
		<map>
			<entry key="AA" value-ref="car1"></entry>
			<entry key="BB" value-ref="car2"></entry>
		</map>
	</property>
</bean>
  • property 标签
<bean id="dataSource" class="edu.just.spring.beans.collections.DataSource">
	<property name="properties">
		<!-- 使用 props 和 prop 子节点为 Properties 属性赋值 -->
		<props>
			<prop key="user">root</prop>
			<prop key="password">password</prop>
			<prop key="jdbcUrl">jdbc:mysql:///test</prop>
			<prop key="driverClass">com.mysql.jdbc.Driver</prop>
		</props>
	</property>
</bean>

使用utility scheme定义集合
使用基本的集合标签定义集合时,不能将集合作为独立的 Bean 定义,导致其他 Bean 无法引用该集合,所以无法在不同 Bean 直接共享集合

<!-- 配置独立的集合 bean, 以供多个 bean 进行引用 -->
 <util:list id="cars">
 	<ref bean="car1"/>
 	<ref bean="car2"/>
 </util:list>
	
<bean id="person4" class="edu.just.spring.beans.collections.Person">
	<property name="name" value="Jack"></property>
	<property name="age" value="100"></property>
	<property name="cars" ref="cars"></property>
</bean>

使用 p 命名空间

<!-- 通过 p 命名空间为 bean 的属性赋值, 需要先导入 p 命名空间, 相对于传统的配置方式更加的简洁. -->
<bean id="person5" class="edu.just.spring.beans.collections.Person" p:name="luwenhe"
	p:age="20" p:cars-ref="car1"></bean>

2.5 自动装配

Spring IOC 容器可自动装配 Bean,需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式

可以使用 autowire 属性指定 自动装配 的方式.
byName: 根据 bean 的名字(id 的 值)和当前 bean 的 setter 风格的属性名进行自动装配,若有匹配的,则进行自动装配,若没有匹配的,则不装配
byType: 根据 bean 的类型和当前 bean 的属性的类型进行自动装配,若 IOC 容器中有 1 个以上的类型匹配的 bean,则抛出异常

缺点: 如果只希望装配个别属性时, autowire 就不够灵活,autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之。在实际项目中很少使用自动装配功能, 因为和自动装配功能所带来的好处比起来, 明确清晰的配置文档更加具有说服力

<bean id="person" class="edu.just.spring.beans.autowire.Person" p:name="Tim"
	autowire="byName"></bean>
		
<bean id="person" class="edu.just.spring.beans.autowire.Person" p:name="Tim"
	autowire="byType"></bean>

2.6 Bean 之间的关系:继承、依赖

  • 被继承的 Bean 成为父 Bean。继承这个父 Bean 的 Be’an 称为子 Bean
  • 子 Bean 继承父 Bean 的配置,也可以覆盖从父 Bean 继承过来的配置
  • 若只想把父 Bean 作为模板,可以设置 <bean> 的 abstract 属性为 true
  • 也可以忽略父 Bean 的 class 属性,让子 Bean 指定自己的类。此时 abstract 必须设置为 true
<!-- 
	抽象 bean: bean 的 abstract 属性为 true 的 bean. 这样的 bean 不能被 IOC 容器实例化, 只用来被继承配置 
	若某一个 bean 的 class 属性没有指定, 则该 bean 必须是一个抽象 bean
-->
<bean id="address" p:city="Beijing^^" p:street="WuDAOkOU" abstract="true"></bean>
	
<!-- bean 配置的继承: 使用 bean 的 parent 属性指定继承哪个 bean 的配置 -->
<bean id="address2" class="edu.just.spring.beans.autowire.Address"
 	p:street="DaZhongSi" parent="address"></bean>
	
<bean id="car" class="edu.just.spring.beans.autowire.Car"
	p:brand="BenChi" p:price="100000"></bean>
	 
<!-- 要求在配置 Person, 必须有一个关联的 car! 即 person 这个 bean 依赖于 Car 这个 bean -->
<bean id="person" class="edu.just.spring.beans.autowire.Person"
	p:name="Tom" p:address-ref="address2" depends-on="car"></bean>
  • Spring 允许用户通过 depend-on 属性设定 Bean 前置依赖的 Bean,前置依赖 Bean 会在本 Bean 实例化之前创建好

2.7 Bean 的作用域

Spring 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域

  • singleton: 默认值, 容器初始化时创建 bean 实例, 在整个容器的生命周期内只创建这一个 bean, 是单例的
  • prototype: 原型的, 容器初始化时不创建 bean 的实例, 而在每次请求时都创建一个新的 Bean 实例, 并返回
<bean id="car" class="edu.just.spring.beans.autowire.Car" scope="prototype">
	<property name="brand" value="Audi"></property>
	<property name="price" value="20000"></property>
</bean>

2.8 使用外部属性文件

db.properties:

user=root
password=lwh011305
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/fileupload?useSSL=true

导入属性文件:

<!-- 导入属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	<!-- 使用外部化属性文件的属性 -->
	<property name="user" value="${user}"></property>
	<property name="password" value="${password}"></property>
	<property name="driverClass" value="${driverClass}"></property>
	<property name="jdbcUrl" value="${jdbcUrl}"></property>
</bean>

2.9 Spring 表达式语言:SpEL

类似于 EL:SpEL 使用 #{...} 作为定界符,所以在大框号中的字符被认为是 SpEL

为属性赋一个字面量:

<bean id="address" class="edu.just.spring.beans.spel.Address">
	<!-- 使用 spel 为属性赋一个字面值 -->
	<property name="city" value="#{'beijing'}"></property>
	<property name="street" value="wudaokou"></property>
</bean>

使用 SpEL 引用类的静态属性:

<bean id="car" class="edu.just.spring.beans.spel.Car">
	<property name="brand" value="Audi"></property>
	<property name="price" value="2000"></property>
	<!-- 使用 Spel 引用类的静态属性 -->
	<property name="tyrePerimeter" value="#{T(java.lang.Math).PI * 80}"></property>
</bean>

使用 SpEL 来引用其他 Bean

<bean id="person" class="edu.just.spring.beans.spel.Person">
	<property name="name" value="luwenhe"></property>
	
	<!-- 使用 Spel 来引用其他的 Bean 的属性 -->
	<property name="city" value="#{address.city}"></property>
		
	<!-- 使用 Spel 来引用其他的 Bean -->
	<property name="car" value="#{car}"></property>
		
	<!-- 使用 Spel 中使用运算符 -->
	<property name="info" value="#{car.price > 30000 ? '金领' : '白领'}"></property>
</bean>

2.10 IOC 容器中 Bean 的生命周期方法

Spring IOC 容器对 Bean 的生命周期进行管理的过程:

  • 通过构造器或者工厂方法创建 Bean 实例
  • 为 Bean 的属性设置值和对其他 Bean 的引用
  • 调用 Bean 的初始化方法
  • Bean 可以使用了
  • 当容器关闭时,调用了 Bean 的销毁方法

创建 Bean 方法

public class Car {

	public Car() {
		System.out.println("Car's Constructor ... ");
	}
	
	private String brand;
	
	public void setBrand(String brand) {
		System.out.println("setBrand ... ");
		this.brand = brand;
	}
	
	public String getBrand() {
		return brand;
	}
	
	public void init() {
		System.out.println("init ... ");
	}
	
	public void destory() {
		System.out.println("destroy ... ");
	}

	@Override
	public String toString() {
		return "Car [brand=" + brand + "]";
	}
}

为 Bean 设置属性值:init-methoddestory-method 属性为 Bean 指定初始化和销毁方法

<bean id="car1" class="edu.just.spring.beans.cycle.Car"
	init-method="init" destroy-method="destory">
	<property name="brand" value="Audi"></property>
</bean>

调用 Bean 的初始化方法

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");
		
Car car = (Car) ctx.getBean("car1");
System.out.println(car);
		
ctx.close();

输出:

Car's Constructor ... 
setBrand ... 
init ... 
Car [brand=Audi]
六月 28, 2018 5:24:15 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:24:14 CST 2018]; root of context hierarchy
destroy ... 

创建 Bean 的后置处理器

  • Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外处理
  • Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理,而非单一实例
  • 需要实现 BeanPostProcessor 接口

Spring IOC 容器对 Bean 的生命周期进行管理的过程

  • 通过构造器或者工厂方法创建 Bean 实例
  • 为 Bean 的属性设置值和对其他 Bean 的引用
  • 将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
  • 调用 Bean 的初始化方法
  • 将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization 方法
  • Bean 可以使用
  • 当容器关闭时,调用 Bean 的销毁方法

实现 BeanPostProcessor 接口:
bean: bean 实例本身
beanName: IOC 容器配置的 bean 的名字.
返回值: 是实际上返回给用户的那个 Bean,注意:可以在以上两个方法中修改返回的 Bean,甚至返回一个新的 Bean

public Object postProcessBeforeInitialization(Object bean, String beanName):init-method 之前被调用
public Object postProcessAfterInitialization(Object bean, String beanName):init-method 之后被调用的实现

public class MyBeanPostProcessor implements BeanPostProcessor{
		
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessBeforeInitialization: " + bean + ", " + beanName);
		
		if("car".equals(beanName)) {
			//..
		}
		
		return bean;
	}
	
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("postProcessAfterInitialization: " + bean + ", " + beanName);
	
		Car car = new Car();
		car.setBrand("Ford");
		return car;
	}
} 

配置 Bean

<!-- 配置 Bean 的后置处理器: 不需要配置 id, IOC 容器自动识别是一个 BeanPostProcessor -->
<bean class="edu.just.spring.beans.cycle.MyBeanPostProcessor"></bean>

输出:

Car's Constructor ... 
setBrand ... 
postProcessBeforeInitialization: Car [brand=Audi], car1
init ... 
postProcessAfterInitialization: Car [brand=Audi], car1
Car's Constructor ... 
setBrand ... 
Car [brand=Ford]
六月 28, 2018 5:53:28 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@6438a396: startup date [Thu Jun 28 17:53:27 CST 2018]; root of context hierarchy
destroy ... 

2.11 泛型依赖注入

泛型依赖注入:子类之间的依赖关系由其父类泛型以及父类之间的依赖关系来确定,父类的泛型必须为同一类型

BaseRepository 类

public class BaseRepository<T> {}

*UserRepository 类:*标识持久层

@Repository
public class UserRepository extends BaseRepository<User>{}

BaseService 类: 通过 Autowired 自动装配 BaseRepository 实例

public class BaseService<T> {

	@Autowired
	protected BaseRepository<T> repository;
	
	public void add() {
		System.out.println("add ...");
		System.out.println(repository);
	}
	
}

UserService 类: 通过父类的泛型实例,在 UserService 中已经注入了 UserRepository 实例

@Service
public class UserService extends BaseService<User>{}

输出:

add ...
edu.just.spring.beans.generic.di.UserRepository@799d4f69

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

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

相关文章

Sectigo中间证书根证书说明

Sectigo SSL证书产品证书链主要分为两个版本&#xff0c;常见的的一种版本多&#xff0c;但随着安全性提升&#xff0c;证书链的加载方式变化&#xff0c;第二种版本证书链更具备安全需要&#xff0c;对此做了详细说明。一、兼容性最高版本&#xff0c;根证书算法&#xff1a;s…

BI 是如何数据分析的?

企业部署商业智能BI前&#xff0c;需要进行详细的分析&#xff0c;了解BI能为企业带来多少价值&#xff1f;如何提高工作效率的等等&#xff0c;今天我们就来聊一聊 BI 的工作原理。 一、BI的取数方式 商业智能BI是通过访问和连接业务系统数据源数据库的方式来进行取数的&…

记录gitlab和jenkins集成的过程

gitlab设置外发请求 首先在前面的几篇文章中&#xff0c;我们的gitlab和jenkins都安装好了&#xff0c;在这里我们就可以对gitlab 和jenkins进行集成操作处理。 首先设置gitlab的外发请求,如图所示: 先点击管理员&#xff0c;进入到管理中心后 先点击设置&#xff0c;然后点击…

劲霸男装:400+门店的销售佣金管理,如何实现一键发薪

陪伴一代人记忆的劲霸男装&#xff08;下文简称「劲霸」&#xff09;&#xff0c;很多人应该都不陌生。 他们的门店遍布全国的大型商场及街边店铺&#xff0c;自1980起&#xff0c;发展已40余年&#xff0c;现拥有形象统一、规范管理的品牌专卖店2000多家。他们门店多&#xff…

传输层协议——UDP协议

❣️关注专栏&#xff1a;JavaEE 传输层虽然是操纵系统内核已经实现好了的&#xff0c;但是我们程序猿写代码要调用系统提供的 socket API 完成网络编程&#xff0c;其中 socket 就属于传输层部分。 &#x1f331; UDP协议 &#x1f331; 1 UDP协议端格式 上图就是UDP协议报…

Java面向对象特征之三:多态

一&#xff1a;面向对象三大特征之三&#xff1a;多态 1.多态是什么&#xff1f; 同类型的对象&#xff0c;执行同一个行为&#xff0c;会表现出不同的行为特征。 比如&#xff1a;猫和狗都是动物类型&#xff0c;执行同一个行为&#xff0c;但是会表现出不同的行为特征&…

flink sql 源码走读 --- 解释flink jdbc where 条件为什么没有下推数据库

本文通过一个具体案例&#xff0c;说明 flink sql 如何实现 connector 加载、source/sink 端操作、数据库连接等。可以帮助大家了解其原理&#xff0c;并在代码中找到落库执行SQL生成逻辑&#xff0c;得到where条件并没有下推到库执行的结论。 案例如下&#xff1a; create t…

Zookeeper集群和Hadoop集群安装(保姆级教程)

1. HA HA&#xff08;Heigh Available&#xff09;高可用 解决单点故障&#xff0c;保证企业服务 7*24 小时不宕机单点故障&#xff1a;某个节点宕机导致整个集群的宕机 Hadoop 的 HA NameNode 存在单点故障的可能&#xff0c;需要配置 HA 解决引入第二个 NameNode 作为备份同…

C语言学习(三)

#include <stdio.h> int main(void){int a; scanf("%d",&a); printf("%d",a); return 0&#xff1b;} 正在上传…重新上传取消正在上传…重新上传取消&符号作用是把键盘中输入的值给变量a,使用scanf()时输入数值&#xff0c;需要按一下enter…

MySQL知识点全面总结2:Mysql语句的执行(DDL DML 完整性约束)

二.MySQL知识点全面总结2&#xff1a;mysql语句的执行&#xff08;DDL DML 完整性约束&#xff09; 1.对数据库的操作&#xff08;DDL&#xff09; 2.对数据表的操作&#xff08;DDL&#xff09; 3.对数据表字段的操作&#xff08;DDL&#xff09; 4.对数据表内容的增删改&…

Science Direct 高级检索、使用技巧、寻找目标期刊、E lsevi er 投稿指南

ScienceDirect使用教程&E ls evier投稿指南1. 高级检索功能1.1 布尔值运算符和短语搜索&#xff08;构建检索式&#xff09;1.2 搜索特殊字符和公式1.3 非搜索用词2. 如何使用搜索结果页面&#xff1f;3. 下载多个文档3.1 从搜索结果列表中下载多个文档3. 利用 JournalFind…

java高性能并发计数器之巅峰对决

并发计数器各个方案介绍方案概述1. jdk5提供的原子更新长整型类 AtomicLong2. synchronized3. jdk8提供的 LongAdder 【单机推荐】4. Redisson分布式累加器【分布式推荐】方案介绍jdk5提供的原子更新长整型类 AtomicLong在JDK1.5开始就新增了并发的Integer/Long的操作工具类Ato…

VS2022+qt5.14.2配置qcustomplot2.1.16(坑很多)

目录1. 前言2. 下载QCustomPlot的源码3. 将QCustomPlot添加到QT项目&#xff08;一些遇到的问题&#xff09;1. 前言 QCustomPlot 是一个超强超小巧的qt绘图类&#xff0c;非常漂亮&#xff0c;非常易用&#xff0c;只需要加入一个qcustomplot.h和qcustomplot.cpp文件即可使用…

Android 基础知识4-3.7 ProgressBar(进度条)详解

一、简介 ProgressBar&#xff08;进度条&#xff09;是UI界面中一种非常实用的组件&#xff0c;通常用于向用户像是某个耗时操作完成的百分比。进度条可动态地显示进度&#xff0c;因此避免长时间地执行某个操作时&#xff0c;让用户感觉程序失去了响应&#xff0c;从而更好地…

常用反弹 shell 方式总结

在对 Linux 系统进行渗透测试中&#xff0c;常常会用到反弹 shell 的操作&#xff0c;今天来总结一下常用反弹 shell 的方式。 什么是反弹shell&#xff1a; 反弹shell&#xff0c;就是攻击机监听在某个TCP/UDP端口为服务端&#xff0c;目标机主动发起请求到攻击机监听的端口…

Spark 配置项

Spark 配置项硬件资源类CPU内存堆外内User Memory/Spark 可用内存Execution/Storage Memory磁盘ShuffleSpark SQLJoin 策略调整自动分区合并自动倾斜处理配置项分为 3 类: 硬件资源类 : 与 CPU、内存、磁盘有关的配置项Shuffle 类 : Shuffle 计算过程的配置项Spark SQL : Spar…

MySQL 中的 distinct 和 group by 的性能比较

1 先说大致的结论&#xff08;完整结论在文末&#xff09;在语义相同&#xff0c;有索引的情况下&#xff1a;group by和 distinct 都能使用索引&#xff0c;效率相同。在语义相同&#xff0c;无索引的情况下&#xff1a;distinct 效率高于group by。原因是 distinct 和 group …

【软件开发】基于PyQt5开发的标注软件

这里是基于PyQt5写的面向目标检测的各类标注PC端软件系统。目前现有的labelme软件和labelImg开源软件无法满足特殊数据集的标注要求&#xff0c;而且没有标注顺序的报错提示。当然我设计的软件就会不具有适用性了&#xff08;毕竟从下面开发的软件可以明显看出来我做的基本上是…

spark-submit报错

spark-submit --class ${main_class} \ --master yarn \ --deploy-mode client \ --driver-memory 8g \ --executor-memory 6g \ --num-executors 1 \ --executor-cores 34 \ ${HOME_PATH}/obs_finance-1.0-SNAPSHOT-jar-with-dependencies.jar ${year_month} 注意这个34超过…

【教学典型案例】28.单表的11个Update接口--MyBatis

目录一&#xff1a;背景介绍二&#xff1a;前期准备引入pom依赖MyBatis配置文件数据库连接文件MyBatis配置类三&#xff1a;代码编写Mapper编写接口通用mapper实体pojojunit测试编写测试结果四&#xff1a;总结一&#xff1a;背景介绍 在进行项目开发编写更新接口时&#xff0…