Java面试题,Spring Bean的注册与依赖注入

news2024/9/24 23:30:01

Spring Bean的注册与依赖注入

  • 一、XML文件中,将Bean创建到Spring容器
    • 1. 基本类型注册
    • 2. 类装配
    • 3. 有参构造方法装配
    • 4. 扩展注入
    • 5. Bean的作用域
    • 6. Bean的其他配置
  • 二、配置类中,将Bean创建到Spring容器
    • 1. 在mapper、service、controller中创建,等着被componentScan扫描到Spring容器中
    • 2. 在JavaConfig配置类中创建Bean
  • 三、Spring的三种装配机制(XML、JavaConfig、自动装配)
    • 1. 在xml中显式装配
    • 2. 在JavaConfig配置类中显式装配
    • 3. 自动装配
      • 3.1 xml方式自动装配
      • 3.1 使用注解自动装配
  • 四、Bean创建的原理
    • 1. UserService实例化,生成普通对象
    • 2. 使用@Autowired,对普通对象的属性进行依赖注入
    • 3. 初始化(执行UserService中的所有方法)
    • 4. 初始化后(AOP),创建代理对象
    • 5. 将普通对象或者代理对象放入,Map<beanName,Bean对象>
  • 五、创建Bean过程中,推断所使用的构造方法
    • 情形1. 没有写出构造器,默认存在一个无参构造器
    • 情形2. 写一个有参构造器,那么构造器就只有这个有参构造器
    • 情形3. 写一个无参构造器和一个有参构造器,那么就存在两个构造器
    • 情形4. 编写一个有参构造器,那么就存在一个有参构造器
    • 情形5. 编写如下两个有参构造器
    • 情形6. 那么有没有办法使用指定的构造方法?通过@Autowired实现
    • 7. 谁向有参构造器public UserService(OrderService orderService)中传入参数?
    • 8. Spring怎样从Map<beanName,Bean对象>中,找到合适的Bean对象传入有参构造器的参数中?
    • 9. 循环依赖
  • 六、依赖注入
    • 1. 先根据类型type,再根据id
    • 2. 依赖注入的三种方式(属性、set方法、有参构造)

一、XML文件中,将Bean创建到Spring容器

1. 基本类型注册

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student{
	private String name;
	private Address address;
	private String[] books;
	private List<String> hobbys;
	private Map<String String> card;
	private Set<String> games;
	private String wife;
	private Properties info;
}
<bean id="student" class="com.kuang.pojo.Student">
	<!--1. 普通注入-->
	<property name="name" value="狂神说"/>

	<!--2. 数组注入-->
	<property name="books">
		<array>
			<value>红楼梦</value>
			<value>西游记</value>
			<value>水浒传</value>
		</array>
	</property>

	<!--3. List注入-->
	<property name="hobbys">
		<list>
			<value>看书</value>
			<value>听歌</value>
			<value>打球</value>
		</list>
	</property>

	<!--4. Map注入-->
	<property name="card">
		<map>
			<entry key=“身份证” value=“12315454512312”/>
			<entry key=“银行卡” value=“15465415123156”/>
		</map>
	</property>

	<!--5. 数组注入-->
	<property name="games">
		<set>
			<value>红楼梦</value>
			<value>西游记</value>
			<value>水浒传</value>
		</set>
	</property>

	<!--6. 空值注入-->
	<property name="wife">
		<null/>
	</property>

	<!--7. Properties注入-->
	<property name="info">
		<props>
			<prop key="driver">20190525</prop>
			<prop key="url">男/prop>
			<prop key="username">root</prop>
			<prop key="password">123456</prop>
		</props>
	</property>
</bean>

2. 类装配

<!--1. 类装配-->
	<!--csBean类有两个属性:title和author-->
    <bean name="cdBean" class="com.my.spring.bean.CDBean">
        <property name="title" value="The World!!"/>
        <property name="author" value="Mr.D"/>
    </bean>    
     <!--csPlayer类有一个属性:cdBean-->
     <!--对csPlayer的属性csBean进行依赖注入,称为Bean装配,或者依赖关系注入-->
    <bean name="cdPlayer" class="com.my.spring.service.impl.CDPlayerImpl">
        <property name="cdBean" ref="cdBean"/>
    </bean>

3. 有参构造方法装配

<!--2. 有参构造方法1-->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <constructor-arg index="0" value="方法1"/>
    </bean>
<!--3. 有参构造方法2-->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <constructor-arg type="java.lang.String" value="方法2"/>
    </bean>
<!--4. 有参构造方法3-->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <constructor-arg name="name" value="方法3"/>
    </bean>

4. 扩展注入

  • p命名空间注入
1. 先在beans框架中加入支持:xmlns:p="http://www/springframework.org/schema/p"
<!--p命名空间注入,可以直接注入属性的值,property-->
<bean id="user" class="com.kuang.pojo.User" p:name="小李" p:age="10"/>
  • c命名空间注入
1. 先在beans框架中加入支持:xmlns:c="http://www/springframework.org/schema/c"
2. 其次使用c注入的Bean必须存在有参构造器
<!--c命名空间注入,通过构造器注入,construct-args-->
<bean id="user" class="com.kuang.pojo.User" c:name="小李" c:age="10"/>

5. Bean的作用域

  1. 单例模式(Spring默认机制):从Spring容器中get的每个对象都是同一个对象。
<bean id="user" class="com.kuang.pojo.User" scope="singleton"/>
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user1 = context.getBean("user");
User user2 = context.getBean("user");
System.out.println(user1==user2);	//true
  1. 原型模式:每次从容器中get的时候,都会产生一个新对象
<bean id="user" class="com.kuang.pojo.User" scope="prototype"/>
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user1 = context.getBean("user");
User user2 = context.getBean("user");
System.out.println(user1==user2);	//false

6. Bean的其他配置

6.1. 别名

<!--别名,如果添加了别名,我们可以使用别名获取这个对象-->
<alias name="user" alias="userNew">

<!--
	id:bean的唯一标识符,也就是相当于我们学的对象名
	class:bean对象所对应的全限定名:包名+类型
	name:也是别名,而且那么可以同时取多个别名
-->
	<bean id="user" class="com.kuang.pojo.user" name="user1,user2,user3">
	<property name="name" value="狂神说"/>
	</bean>

6.2 Import(一般用于团队开发使用,他可以将多个配置文件,导入合并为一个)
注意:如果导入的文件中,bean重名了,那么就会把重名的bean合并成一个,所以不会因为不同的bean.xml存在重名而发生冲突

<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

二、配置类中,将Bean创建到Spring容器

1. 在mapper、service、controller中创建,等着被componentScan扫描到Spring容器中

/*
	在Spring容器中创建一个bean
	<bean id="orderService" class="com.kuang.Service.OrderService">
*/
@Component
public class OrderService{
}

2. 在JavaConfig配置类中创建Bean

/*
	在Spring容器中创建一个bean
	<bean id="orderService1" class="com.kuang.Service.OrderService">
*/
@Configuration
@ComponentScan
public class AppConfig{
	@Bean
	public OrderService orderService1(){
		return new OrderService();
	}
}

三、Spring的三种装配机制(XML、JavaConfig、自动装配)

1. 在xml中显式装配

<!--1. 类装配-->
	<!--csBean类有两个属性:title和author-->
    <bean name="cdBean" class="com.my.spring.bean.CDBean">
        <property name="title" value="The World!!"/>
        <property name="author" value="Mr.D"/>
    </bean>    
     <!--csPlayer类有一个属性:cdBean-->
     <!--对csPlayer的属性csBean进行依赖注入,称为Bean装配,或者依赖关系注入-->
    <bean name="cdPlayer" class="com.my.spring.service.impl.CDPlayerImpl">
        <property name="cdBean" ref="cdBean"/>
    </bean>

2. 在JavaConfig配置类中显式装配

  • 实体类
@Component
public class User {
    private String name;
    public String getName() {
        return name;
    }
    @Value("黑心白莲") //属性注入值
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • 配置类
// @Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@ComponentScan
public class KuangConfig {
    /* 
    	@bean == bean标签
    	方法名字 == bean标签中id属性
    	方法返回值 == bean标签中的class属性
	*/
    @Bean
    public User user(){
        return new User(); 
    }
}
  • 测试类
public class MyTest {
    public static void main(String[] args) {
        //如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
        ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);
        User user = context.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

3. 自动装配

3.1 xml方式自动装配

byName: 会自动在容器上下文查找,和自己对象set方法后面的值对应的bean id(通过id匹配)

//实体类
@Data
public class Pepole {
    private String name;
    private Books books;
    private Hobbies hobbies;
    <bean id="books" class="com.lmy.pojo.Books"/>
    <bean id="hobbies" class="com.lmy.pojo.Hobbies"/>

    <bean id="pepole" class="com.lmy.pojo.Pepole" autowire="byName">
        <property name="name" value="zhangSan"/>
    </bean>

byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean(通过class匹配)
注意:使用autowire byType首先需要保证:同一类型的bean对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

    <bean id="books" class="com.lmy.pojo.Books"/>
    <bean id="hobbies" class="com.lmy.pojo.Hobbies"/>

    <bean id="pepole" class="com.lmy.pojo.Pepole" autowire="byType">
        <property name="name" value="zhangSan"/>
    </bean>

3.1 使用注解自动装配

注解开发注意事项
@Autowied装配方式
按类型装配(默认使用的装配方式)。
按名称装配(结合@Qualifier注解使用)。

public class Pepole {
    private String name;
//1. 通过名字装配
    @Autowired
    @Qualifier("books1")
    private Books books;
//2. 通过类型装配
    @Autowired
    private Hobbies hobbies;
}
	<!--开启属性注解支持!-->
    <context:annotation-config/>

    <bean id="books2" class="com.lmy.pojo.Books"/>
    <bean id="books1" class="com.lmy.pojo.Books"/>
    <bean id="hobbies" class="com.lmy.pojo.Hobbies"/>
    <bean id="pepole" class="com.lmy.pojo.Pepole"/>

@Resource装配方式
@Resource指定按type自动装配

    @Resource(type = Books.class)
    private Books books;

@Resource指定按name自动装配:

    @Resource(name = "books")
    private Books books;

@Autowired与@Resource区别
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、Bean创建的原理

这段代码中@mapper,实际上执行了Spring创建Bean对象并放入Spring容器的过程

@mapper
public class UserService{
	@Autowired
	private OrderService orderService;
	public void test(){
		System.out.println(orderService);
	}
}
  1. UserService实例化(无参构造方法),生成普通对象
  2. 对普通对象依赖注入- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -【根据@Autowired判断是否对属性注入依赖】
  3. 初始化- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -【执行所有方法】
  4. 初始化后(AOP),生成代理对象 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -【切面编程】
  5. 将普通对象或者代理对象放入,Map<beanName,Bean对象>(单例池) -【即注册Bean对象】

1. UserService实例化,生成普通对象

这里的UserService实例化,可不是说让你自己在main()方法里面手动做一个UserService userService的实例化。而是说你在public class UserService“头顶”上加了注解@Mapper的时候,Spring“背地里”进行了第一步:将UserService实例化了

2. 使用@Autowired,对普通对象的属性进行依赖注入

  • 在UserService对象中有一个属性OrderService,Spring也对该属性进行了实例化OrderService orderService。但是实例化出来的普通对象orderService是没有值的,通过@Autowired的依赖注入,向普通对象orderService注入,普通对象orderService就有了值,

3. 初始化(执行UserService中的所有方法)

//初始化,执行UserService中的所有方法,全都成功后才能将Bean对象创建并放入Map
if (userService instanceof InitializingBean){
	((InitializingBean) userService).afterPropertiesSet();
}

为什么要执行初始化这个步骤呢?换句话说,为什么要执行所有方法呢?

//1. 通过执行方法来为创建的实例的属性admin注入值为xxx
@Override
public void afterPropertiesSet() throws Exception{
	this.admin = "xxx";
}

//2. 通过执行方法来检验创建的实例是否满足
public void afterPropertiesSet() throws Exception{
	if(sqlSession == null){
		throw new NullPointerException();
	}
}

/*
3. 个人项目经历:每个属性都要get/set方法,若是缺失了某个属性的get/set方法,
Spring启动就会报错,这也说明了初始化执行了Bean对象的所有方法
*/

4. 初始化后(AOP),创建代理对象

AOP就是对注入依赖后的普通对象进行切面编程,从而生成代理对象。至于什么是切面编程AOP,读者就自行搜索一下吧,因为我也只是一知半解。

5. 将普通对象或者代理对象放入,Map<beanName,Bean对象>

  • 我们先看到回到上面Spring创建Bean对象的过程,会发现有普通对象和代理对象。两者的区别,大家可以认为是普通对象经过了“加工”,变成了更多功能的代理对象。
  • 现在我们要将普通对象或者代理对象放入Map并将代理对象放入Map<beanName,Bean对象>中。
  • 如果没有进行AOP生成代理对象,那么这时候就是将普通对象放入Map中,普通对象成为Bean对象;如果进行了AOP生成代理对象,那么这时候就是将代理对象放入Map中,代理对象成为Bean对象;
  • 将普通对象或者代理对象放入Map这个动作完成了,才是真正意义上生成了Bean对象,也就是注册了Bean

五、创建Bean过程中,推断所使用的构造方法

情形1. 没有写出构造器,默认存在一个无参构造器

@Service
public class UserService{
	private OrderService orderService;
	public void test(){				//初始化会自动执行全部方法,所以test方法会被自动执行
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
输出:null

情形2. 写一个有参构造器,那么构造器就只有这个有参构造器

@Service
public class UserService{
	private OrderService orderService;
	public UserService(OrderService orderService){
		this.orderService = orderService;
		System.out.println(1);
	}
	public void test(){
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
输出:1、#{orderService指针编号}

情形3. 写一个无参构造器和一个有参构造器,那么就存在两个构造器

@Service
public class UserService{
	private OrderService orderService;
	public UserService(){
		System.out.println(0);
	}
	public UserService(OrderService orderService){
		this.orderService = orderService;
		System.out.println(1);
	}
	public void test(){
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
输出:0、null

情形4. 编写一个有参构造器,那么就存在一个有参构造器

@Service
public class UserService{
	private OrderService orderService;
	public UserService(OrderService orderService1,OrderService orderService2){
		this.orderService = orderService;
		System.out.println(2);
	}
	public void test(){
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
输出:2、#{orderService指针编号}

情形5. 编写如下两个有参构造器

@Service
public class UserService{
	private OrderService orderService;
	public UserService(OrderService orderService){
		this.orderService = orderService;
		System.out.println(1);
	}
	public UserService(OrderService orderService1,OrderService orderService2){
		this.orderService = orderService;
		System.out.println(2);
	}
	public void test(){
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
报错!Caused by:com.zhouyu.service.UserService.< init >()

总结

  • 如果没有重写构造方法,那么创建Bean对象就会用无参构造方法;
  • 如果重写了一个有参构造方法,那么创建Bean对象就会用该有参构造方法;
  • 如果重写了两个有参构造方法,那么创建Bean对象不知道用哪个有参构造方法,就会去寻找无参构造方法,如果没有无参构造方法就报错。如果存在无参构造方法就执行无参构造方法。

情形6. 那么有没有办法使用指定的构造方法?通过@Autowired实现

@Service
public class UserService{
	private OrderService orderService;
	
	@Autowired		//指定使用该构造方法,即使存在无参构造器,也要使用这个有参构造器
	public UserService(OrderService orderService){
		this.orderService = orderService;
		System.out.println(1);
	}
	public UserService(OrderService orderService1,OrderService orderService2){
		this.orderService = orderService;
		System.out.println(2);
	}
	public void test(){
		System.out.println(orderService);
	}
}

执行UserService userService = (UserService) applicationContext.getBean(“UserService”);
输出:1、#{orderService指针编号}

7. 谁向有参构造器public UserService(OrderService orderService)中传入参数?

  • 当我们创建Bean对象userService时,需要用到有参构造方法,Spring就会在Map中寻找Bean对象OrderService,并且注入到构造方法的参数orderService中。
  • 如果将@Component去掉,那么OrderService就无法成为Bean对象,那么Spring也拿不出Bean对象来传给UserService的有参构造方法的参数orderService,那么orderService就为空。但是Spring规定了不能向有参构造方法的参数传null。所以这种情况运行就会出现报错:No qualifying bean of type ‘com.zhouyu.service.OrderService’

8. Spring怎样从Map<beanName,Bean对象>中,找到合适的Bean对象传入有参构造器的参数中?

  • 如果通过参数的类OrderService找出beanName唯一,那就直接将Bean对象注入orderService。
  • 如果通过参数的类OrderService找出beanName不唯一,那就通过参数名orderService找出唯一的beanName,然后将Bean对象注入orderService参数
  • 如果这样都找不到,那就报错!
  • 如下这三个orderService,orderService1,orderService2分别是可选的beanName,将构造器public UserService(OrderService orderService)的参数orderService改成上述之一即可不报错:expected single matching bean but found 3:orderService,orderService1,orderService2
//1. 注册了一个类型为OrderService,名字为orderService的Bean
public class OrderService{
}

//2. 注册了一个类型为OrderService,名字为orderService1的Bean
public class AppConfig{
	@Bean
	public OrderService orderService1(){
	}
}

9. 循环依赖

@Component
public class OrderService{
	private UserService userService;
	public OrderService(UserService userService){
		this.userService = userService;
	}
}
@Service
public class UserService{
	private OrderService orderService;
	public UserService(OrderService orderService){
		this.orderService = orderService;
	}
}
报错:Is there an unresolvable circular reference?

我们来看一下过程:当我要将UserService创建为Bean对象时,那么就需要传入OrderService的Bean对象给orderService。那么OrderService要提前被Spring创建为Bean对象是不是?那我们看看OrderService要提前被Spring创建为Bean对象也是用到有参构造器,需要传入UserService的Bean对象,那么UserService要提前被Spring创建为Bean对象…这样就陷入了循环了(circular reference)

六、依赖注入

1. 先根据类型type,再根据id

  1. 为Spring容器中注册以下两个类
/*
	在Spring容器中创建一个bean
	<bean id="orderService1" class="com.kuang.Service.OrderService">
	<bean id="orderService2" class="com.kuang.Service.OrderService">
	
*/
@Configuration
@ComponentScan
public class AppConfig{
	@Bean
	public OrderService orderService1(){
		return new OrderService();
	}
	@Bean
	public OrderService orderService2(){
		return new OrderService();
	}
	
}

2. 依赖注入的三种方式(属性、set方法、有参构造)

public class UserService{
	//1. 属性注入,先根据OrderService类名,再根据orderService1参数名寻找BeanName
	@Autowired
	private OrderService orderService1;
	
	//2. set方法注入,先根据OrderService类名,再根据orderService参数名寻找BeanName
	@Autowired
	public void setOrderService(OrderService orderService1){
		this.orderService1 = orderService1;
	}

	//3. 有参构造器方法注入,先根据OrderService类名,再根据orderService参数名寻找BeanName
	public UserService(OrderService orderService1){
		this.orderService = orderService1;
	}
}

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

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

相关文章

计网必会:HTPP详解(非常全面)、cookie、缓存

文章目录应用层协议Web和HTTPHTTP 概述采用非持续连接的HTTPRTT 往返时间的定义**三次握手过程**采用持续连接的HTTPHTTP到底采用哪个&#xff1f;HTTP 的报文格式请求报文功效格式响应报文状态码格式Cookie什么是cookieWeb缓存在学习的过程很多人都遇到了HTTP和Cookie&#xf…

卓有成效的五种用例设计方法

持续坚持原创输出&#xff0c;点击蓝字关注我吧用例设计作为测试工程师的立身之本&#xff0c;是衡量测试工程师综合素质的重要参考&#xff0c;时间是测试工作中重要的测试资源&#xff0c;通过设计高质量的测试用例可以有效地提升测试效率。本文旨在介绍测试工作中常用的五种…

SSO笔记

自己学习做的笔记.没有具体代码 单点登录:多系统,单一位置登录,实现多系统同时登录的一种技术. 也就是说多个应用系统中&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统。 和三方登录Oauth2是有区别的.Oauth2属于三方登录.通常是某系统,使用其他系统的用户,…

【机器学习】多分类及多标签分类算法(含源代码)

目录&#xff1a;多分类及多标签分类算法一、单标签二分类问题1.1 单标签二分类算法原理二、单标签多分类问题2.1 ovo2.1.1 手写代码2.1.2 调用API2.2 ovr2.2.1 手写代码2.2.2 调用API2.3 OvO和OvR的区别2.4 Error Correcting三、多标签算法问题3.1 Problem Transformation Met…

Vue3 – Composition API(二)

1、computed函数使用 1.1、computed 在前面我们讲解过计算属性computed&#xff1a;当我们的某些属性是依赖其他状态时&#xff0c;我们可以使用计算属性来处理 在前面的Options API中&#xff0c;我们是使用computed选项来完成的&#xff1b;在Composition API中&#xff0c…

Shell语法

一、概念 Shell 是命令行与操作系统沟通的桥梁&#xff0c;也是一门语言。 Shell 脚本可以直接在命令行中执行&#xff0c;也可以作为文件方便复用。 Linux中常见的 Shell 脚本有&#xff1a; Bourne Shell(/usr/bin/sh或/bin/sh)Bourne Again Shell(/bin/bash)C Shell(/us…

《啊哈算法第四章之bfs》(17张图解)

源自《啊哈算法》 目录 bfs正文 题目 思路 完整代码1 完整代码2 再解炸弹人 题目 思路 完整代码1 完整代码2 总结 bfs正文 第四章--深度优先搜索中&#xff0c;我们用dfs找到了寻找小哈的最短路径 接下来&#xff0c;我们要用bfs&#xff08;Breadth First Sear…

04 |「链表」简析

前言 前言&#xff1a;研究一个数据结构的时候&#xff0c;首先讲的是增删改查。 文章目录前言一、链表简介1. 含义2. 节点组成3. 存储方式1&#xff09;数据在内存中的存储方式2&#xff09;单链表在内存中的存储方式3&#xff09;双链表在内存中的存储方式4&#xff09;循环链…

python-38-降低内存开销的python迭代器

【进阶Python】第五讲&#xff1a;迭代器与生成器 python 迭代器和生成器 迭代是Python中常用且非常强大的一个功能&#xff0c;它可以用于访问集合、列表、字符串、字典等数据结构的元素。 我们经常使用循环和条件语句&#xff0c;我们也清楚哪些是可以迭代访问&#xff0c;但…

结构型模式-代理模式

1.概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时&#xff0c;访问对象不适合或者不能直接引用目标对象&#xff0c;代理对象作为访问对象和目标对象之间的中介。 Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译…

Nacos 配置中心源码讲解

目录 1. 配置中心的优点 2. 配置模型结构 3. 配置中心 Server 端实现原理 3.1 新建配置 / 发布配置 3.2 查询配置 4. 配置中心 Client 端实现原理 4.1 发布配置 4.2 查询配置 4.3 监听机制 Listener 1. 配置中心的优点 运行时动态修改系统参数配置&#xff0c;不用重启…

排序算法解析:快排,归并 (全)

一、快排原始快排 算法思想&#xff1a;ps&#xff1a;排序的效果其实就是使一个数列中的每个数都满足左边数比它小、右边数比它大&#xff08;假设升序&#xff09;。接下来我们来了解快排&#xff1a;多次递归遍历&#xff0c;每单次遍历&#xff0c;设定一个限定值&#xff…

02 |「数据结构、逻辑结构、物理结构」基本概念简析

前言 前言&#xff1a;简析数据结构、逻辑结构、物理结构。 文章目录前言一、数据结构1. 简介2. 数据3. 结构4. 分析5. 分类1&#xff09;线性结构&#xff08;线性表&#xff09;2&#xff09;树结构3&#xff09;图结构二、逻辑结构与物理结构1. 为什么要有逻辑结构和物理结构…

SpringBoot+Vue--前端搭建-笔记1

前端搭建 首先安装node.js(百度) 官网下载地址&#xff1a;http://nodejs.cn/download 以前写的关于npm 后端了解的npm_biubiubiu0706的博客-CSDN博客 安装Node.js淘宝镜像加速器(cnpm) npm install cnpm -g(可以不安装) #建议使用如下语句解决npm速度慢的问题 好比设置仓…

代码随想录算法训练营三期 day 24 - 回溯 (1) (补)

回溯算法理论基础 什么是回溯法 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。所以以下讲解中&#xff0c;回溯函数也就是递归函数&#xff0c;指的都是一个函数。 回溯法的效率 回溯的本质是穷举&…

【手把手教你学51单片机】中断的优先级

注&#xff1a;本文章转载自《手把手教你学习51单片机》&#xff01;因转载需要原文链接&#xff0c;故无法选择转载&#xff01; 如若侵权&#xff0c;请联系我进行删除&#xff01;上传至网络博客目的为了记录自己学习的过程的同时&#xff0c;同时能够帮助其他一同学习的小伙…

第四十三章 动态规划——最长单调序列模型

第四十三章 动态规划——最长单调序列模型一、最长单调序列模型1、模型母题2、思路分析&#xff08;两种方法&#xff1a;DP&#xff0c;贪心&#xff09;二、模型的应用1、AcWing 1017. 怪盗基德的滑翔翼&#xff08;1&#xff09;问题&#xff08;2&#xff09;分析&#xff…

C规范编辑笔记(十四)

往期文章&#xff1a; C规范编辑笔记(一) C规范编辑笔记(二) C规范编辑笔记(三) C规范编辑笔记(四) C规范编辑笔记(五) C规范编辑笔记(六) C规范编辑笔记(七) C规范编辑笔记(八) C规范编辑笔记(九) C规则编辑笔记(十) C规范编辑笔记(十一) C规范编辑笔记(十二) C规范编辑笔记(…

Linux进程学习【一】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f38a;每篇一句&#xff1a; 图片来源 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…

Linux基本功系列之rename命令实战

文章目录一. rename 命令介绍二. 语法格式及常用选项三. 参考案例3.1 将当前目录下所有.cfg的文件&#xff0c;替换为.txt结尾3.2 将所有出现mufeng的部分都替换为mufeng13.3 将mufeng0开头都变成mufeng00开头3.4 rename支持正则表示式总结前言&#x1f680;&#x1f680;&…