java-spring 图灵 02 手写spring

01.idea中创建一个maven管理的空项目
在这里插入图片描述
02.模拟创建出spring容器类,这里叫wzpApplicationContext,创建的时候会自动加载配置类的数据:

这里wzpApplicationContext对标的是AnnotationConfigApplicationContext

public class wzpApplicationContext {private Class configClass;public wzpApplicationContext(Class configClass) {this.configClass = configClass;}
}

模拟出容器类要扫描的配置类Appconfig

public class Appconfig {
}

在test中去测试这些创建的类

public class Mytest {public static void main(String[] args) {wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);
}
}

03.在wzpApplicationContext 添加getbean函数,获取spring容器中的bean

  public Object getBean(String beanName) {return null;}

创建服务类UserService

public class UserService {
}

在这里插入图片描述

在测试test中运行getbean方法

public class Mytest {public static void main(String[] args) {wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");
}
}

04.在服务类中写一些方法,等会看一下是不是可以运行

public class UserService {public void test(){System.out.println("test");}
}

此时在test中:

public class Mytest {public static void main(String[] args) {wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");userService.test();}}

05.写几个自定义的注解
比如说,spring容器中的扫描,需要注解@ComponentScan
在这里插入图片描述

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {String value() default "";
}

解释一下:
Target 注解是说,这个注解主要用在哪一个区域,TYPE表示类,FIELD表示属性,METHOD表示方法。
Rentention 注解是说,这个注解在那个阶段使用,RUNTIME是在类加载阶段使用

然后模仿spring去用:

@ComponentScan("org.example.wzp.service")
public class Appconfig {}

再创建一个注解:@Component

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {String value() default "";
}

在服务类中去使用:

@Component
public class UserService {public void test(){System.out.println("test");}
}

06.实现扫描的功能
现在只是写了几个注解,具体的功能代码还没有写,接下来就是扫描的代码
回想spring框架,是创建spring容器的时候,就会自动创建bean
所以,扫描的具体实现代码就应该在构造函数中写

//判断类上是不是有注解ComponentScanif(configClass.isAnnotationPresent(ComponentScan.class)){//获取注解对象ComponentScan componentScan = (ComponentScan)configClass.getAnnotation(ComponentScan.class);//获取注解对象上的value,这里也就是pathString path = componentScan.value();//文件的路径是/,而获取到的是带有.的包名path=path.replace(".","/");//获取当前的类加载器ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();//根据类加载器获取编译完成的target的class文件夹的路径URL resource = classLoader.getResource(path);//根据路径,获取文件File file=new File(resource.getFile());//因为扫描的是包,所以大概率是一个目录if (file.isDirectory()){//获取目录中的文件集合for (File f:file.listFiles()){//获取文件的绝对路径String absolutePath = f.getAbsolutePath();//截取从org到classString org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));//由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象String classpath = org.replace("\\", ".");//加载器加载后,得到一个类对象Class<?> aClass = classLoader.loadClass(classpath);//判断是不是类上存在Component注解if(aClass.isAnnotationPresent(Component.class)){//判断是不是单例模式,要看自定义的注解Scopeif (aClass.isAnnotationPresent(Scope.class)){Scope scopeAnnotation = aClass.getAnnotation(Scope.class);String value = scopeAnnotation.value();if (value.equals("singleton")){//创建单例模式的bean}else{//多例模式}}}}}}}

创建一个注解 Scope

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {String value() default "";
}

在服务类上使用,如果是单例,就写singleton,如果是多例,就写prototype

例如:服务类UserService ,这里声明是单例模式

@Component("UserService")
@Scope("singleton")
public class UserService {public void test(){System.out.println("test");}
}

07.优化设计,把类上注解的许多信息都放入到一个对象中的话,直接去读取这个类的属性就好了

创建一个BeanDefinition

public class BeanDefinition {private Class type;private String scope;private Boolean isLazy;public Class getType() {return type;}public void setType(Class type) {this.type = type;}public String getScope() {return scope;}public void setScope(String scope) {this.scope = scope;}public Boolean getLazy() {return isLazy;}public void setLazy(Boolean lazy) {isLazy = lazy;}}

再次优化扫描

 //判断是不是类上存在Component注解if(aClass.isAnnotationPresent(Component.class)){Component componentAnnotation = aClass.getAnnotation(Component.class);String name = componentAnnotation.value();BeanDefinition beanDefinition=new BeanDefinition();beanDefinition.setType(aClass);//判断是不是单例模式,要看自定义的注解Scopeif (aClass.isAnnotationPresent(Scope.class)){Scope scopeAnnotation = aClass.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);if (value.equals("singleton")){//创建单例模式的beanbeanDefinition.setScope("singleton");}else{//多例模式}}}

在wzpApplicationContext 中添加一个属性,map集合

public class wzpApplicationContext {
//配置类private Class configClass;
//存放BeanDefinitionprivate Map<String,BeanDefinition> BeanDefinitionMap =new HashMap<>();}

把刚刚创建的BeanDefinition放入到map集合中:

if(aClass.isAnnotationPresent(Component.class)){Component componentAnnotation = aClass.getAnnotation(Component.class);String name = componentAnnotation.value();BeanDefinition beanDefinition=new BeanDefinition();beanDefinition.setType(aClass);//判断是不是单例模式,要看自定义的注解Scopeif (aClass.isAnnotationPresent(Scope.class)){Scope scopeAnnotation = aClass.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);if (value.equals("singleton")){//创建单例模式的beanbeanDefinition.setScope("singleton");}else{//多例模式}BeanDefinitionMap.put(name,beanDefinition);}}

最后总的代码抽象此外一个方法:
在这里插入图片描述

   public wzpApplicationContext(Class configClass) throws ClassNotFoundException {this.configClass = configClass;//判断类上是不是有注解ComponentScanscan(configClass);}private void scan(Class configClass) throws ClassNotFoundException {if(configClass.isAnnotationPresent(ComponentScan.class)){//获取注解对象ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);//获取注解对象上的value,这里也就是pathString path = componentScan.value();//文件的路径是/,而获取到的是带有.的包名path.replace(".","/");//获取当前的类加载器ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();//根据类加载器获取编译完成的target的class文件夹的路径URL resource = classLoader.getResource(path);//根据路径,获取文件File file=new File(resource.getFile());//因为扫描的是包,所以大概率是一个目录if (file.isDirectory()){//获取目录中的文件集合for (File f:file.listFiles()){//获取文件的绝对路径String absolutePath = f.getAbsolutePath();//截取从org到classString org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));//由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象String classpath = org.replace("\\", ".");//加载器加载后,得到一个类对象Class<?> aClass = classLoader.loadClass(classpath);//判断是不是类上存在Component注解if(aClass.isAnnotationPresent(Component.class)){Component componentAnnotation = aClass.getAnnotation(Component.class);String name = componentAnnotation.value();BeanDefinition beanDefinition=new BeanDefinition();beanDefinition.setType(aClass);//判断是不是单例模式,要看自定义的注解Scopeif (aClass.isAnnotationPresent(Scope.class)){Scope scopeAnnotation = aClass.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);if (value.equals("singleton")){//创建单例模式的beanbeanDefinition.setScope("singleton");}else{//多例模式}BeanDefinitionMap.put(name,beanDefinition);}}}}}}

08.扫描完了,开始写createbean方法了
在扫描之后调用:
用for循环

public class wzpApplicationContext {private Class configClass;private Map<String,BeanDefinition> BeanDefinitionMap =new HashMap<>();public wzpApplicationContext(Class configClass) throws ClassNotFoundException {this.configClass = configClass;//判断类上是不是有注解ComponentScanscan(configClass);for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionMap.entrySet()){BeanDefinition beanDefinition = entry.getValue();String beanName = entry.getKey();if (beanDefinition.getScope().equals("singleton")){//在这里调用createbean,创建单例Object bean=  createBean(beanName,beanDefinition);}}
}

09.在wzpApplicationContext 创建createBean

  private Object createBean(String beanName, BeanDefinition beanDefinition) {return null;}

10.创建的bean要保存到容器

在wzpApplicationContext 创建一个属性 Map<String,Object> singletonObjectsMap,这个用来保存创建的单例bean

  //保存单例的地方,Map集合private Map<String,Object> singletonObjectsMap =new HashMap<>();

此时的for循环

 for (Map.Entry<String, BeanDefinition> entry : BeanDefinitionMap.entrySet()){BeanDefinition beanDefinition = entry.getValue();String beanName = entry.getKey();if (beanDefinition.getScope().equals("singleton")){//创建单例Object  bean=  createBean(beanName,beanDefinition);//保存单例到容器中 singletonObjectsMap.put(beanName,bean);}}

11.什么时候调用这个getbean方法

先从BeanDefinitionMap获取已经扫描完了beanDefinition,如果有的话,那表示在扫描的包中,有这个类,再判断是不是单例模式,如果没有的话,那就说明没有这样的类,抛出异常。

  public Object getBean(String beanName) throws Exception {if (!BeanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);if (beanDefinition.getScope().equals("singleton")){//单例}else{//原型}return null;}

这里是获取bean,单例从容器中获取

singletonObjectsMap.get(beanName)

原型(多例)就马上创建一个bean

createBean(beanName, beanDefinition);

这个时候的getBean方法

    public Object getBean(String beanName) throws Exception {if (!BeanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);if (beanDefinition.getScope().equals("singleton")){//单例return     singletonObjectsMap.get(beanName);}else{//原型Object bean = createBean(beanName, beanDefinition);return bean;}}

12.如何创建bean呢,用反射 newInstance()

   private Object createBean(String beanName, BeanDefinition beanDefinition) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class clazz = beanDefinition.getType();Object o = clazz.getConstructor().newInstance();return o;}

13.测试
在这里插入图片描述
14.创建一个多例

@Component("OrderService")
@Scope("prototype")
public class OrderService
{
}
public class Mytest {public static void main(String[] args) throws Exception {wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");System.out.println((UserService)wzpApplicationContext.getBean("UserService"));System.out.println((UserService)wzpApplicationContext.getBean("UserService"));System.out.println((UserService)wzpApplicationContext.getBean("UserService"));System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));System.out.println((OrderService)wzpApplicationContext.getBean("OrderService"));userService.test();}}

在这里插入图片描述
15.实现依赖注入:也就是@AutoWired注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AutoWired {
}

在服务类UserService中使用这个自定义的注解:

@Component("UserService")
@Scope("singleton")
public class UserService {@AutoWiredprivate OrderService orderService;public void test(){System.out.println("test");}
}

16.测试

结果是null
在这里插入图片描述
17.实现依赖注入
在createBean方法中去写:

private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {Class clazz = beanDefinition.getType();Object o = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()){if (field.isAnnotationPresent(AutoWired.class)){//将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。//实际上setAccessible是启用和禁用访问安全检查的开关//由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的field.setAccessible(true);//Field.set()方法的语法://   set(Object obj, Object value)//      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)field.set(o,getBean(field.getName()));}}return o;}

18.存在一个问题,实现依赖注入的时候,万一那个对象还没有被创建呢,也就是在容器中还没有来得及创建这个类型的bean,要修改getbean方法

public Object getBean(String beanName) throws Exception {if (!BeanDefinitionMap.containsKey(beanName)){throw new NullPointerException();}BeanDefinition beanDefinition = BeanDefinitionMap.get(beanName);if (beanDefinition.getScope().equals("singleton")){Object singletOnobjectBean=  singletonObjectsMap.get(beanName);//单例if (singletOnobjectBean==null){singletonObjectsMap.put(beanName, createBean(beanName,beanDefinition)) ;}return     singletOnobjectBean;}else{//原型Object protoTypeBean = createBean(beanName, beanDefinition);return protoTypeBean;}}

19.实现初始化:
要写一个接口:InitializingBean

public interface InitializingBean {void afterPropertiesSet();
}

20.服务类UserService来实现接口:

@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean {@AutoWiredprivate OrderService orderService;public void test(){System.out.println(orderService);}@Overridepublic void afterPropertiesSet() {System.out.println("初始化");}
}

21.初始化要在创建bean方法中去做啊,所以还是要修改createbean方法:

 private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {Class clazz = beanDefinition.getType();Object o = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()){if (field.isAnnotationPresent(AutoWired.class)){//将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。//实际上setAccessible是启用和禁用访问安全检查的开关//由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的field.setAccessible(true);//Field.set()方法的语法://   set(Object obj, Object value)//      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)field.set(o,getBean(field.getName()));}}//初始化if (o instanceof InitializingBean){((InitializingBean) o).afterPropertiesSet();}return o;}

22.要实现AOP,也就要实现BeanPostProcessor,这个也是一个接口

package org.example.spring;public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName)  {return bean;}
}

23.写这个接口的实现类,因为要在bean中用,所以加上@Component,表示这个也是一个bean

package org.example.spring;
@Component("wzpBeanPostProcessor")
public class wzpBeanPostProcessor  implements  BeanPostProcessor{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {return null;}
}

24.由于这个bean是用于AOP的,比较特殊,所以在扫描的时候创建比较好
,要修改扫描函数,主要是在扫描类中是否有@Component注解修饰的时候这一部分来写比较好

  private void scan(Class configClass) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {if(configClass.isAnnotationPresent(ComponentScan.class)){//获取注解对象ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);//获取注解对象上的value,这里也就是pathString path = componentScan.value();//文件的路径是/,而获取到的是带有.的包名path= path.replace(".","/");//获取当前的类加载器ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();//根据类加载器获取编译完成的target的class文件夹的路径URL resource = classLoader.getResource(path);//根据路径,获取文件File file=new File(resource.getFile());//因为扫描的是包,所以大概率是一个目录if (file.isDirectory()){//获取目录中的文件集合for (File f:file.listFiles()){//获取文件的绝对路径String absolutePath = f.getAbsolutePath();//截取从org到classString org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));//由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象String classpath = org.replace("\\", ".");//加载器加载后,得到一个类对象Class<?> aClass = classLoader.loadClass(classpath);//判断是不是类上存在Component注解if(aClass.isAnnotationPresent(Component.class)){if (BeanPostProcessor.class.isAssignableFrom(aClass)){BeanPostProcessor BeanPostProcessornewInstance = (BeanPostProcessor)aClass.getConstructor().newInstance();BeanPostProcessorList.add(BeanPostProcessornewInstance);}Component componentAnnotation = aClass.getAnnotation(Component.class);String name = componentAnnotation.value();BeanDefinition beanDefinition=new BeanDefinition();beanDefinition.setType(aClass);//判断是不是单例模式,要看自定义的注解Scopeif (aClass.isAnnotationPresent(Scope.class)){Scope scopeAnnotation = aClass.getAnnotation(Scope.class);String value = scopeAnnotation.value();beanDefinition.setScope(value);if (value.equals("singleton")){//创建单例模式的beanbeanDefinition.setScope("singleton");}else{//多例模式}BeanDefinitionMap.put(name,beanDefinition);}}}}}}
 private List<BeanPostProcessor> BeanPostProcessorList=new ArrayList<>();

25.要用这个wzpBeanPostProcessor,主要还是在createbean,这里是初始化后的操作,下面还有一个初始化前的操作

 private Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {Class clazz = beanDefinition.getType();Object o = clazz.getConstructor().newInstance();for (Field field : clazz.getDeclaredFields()){if (field.isAnnotationPresent(AutoWired.class)){//将该对象的可访问标志设置为指定的布尔值。值为true表示当使用该反射对象时应该抑制Java语言访问检查。//实际上setAccessible是启用和禁用访问安全检查的开关//由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的field.setAccessible(true);//Field.set()方法的语法://   set(Object obj, Object value)//      此时的Field对象表示已经是这个对象的一个属性了  为Field对象属于的变量的属性设置新值(Field代表的属性的新的值)field.set(o,getBean(field.getName()));}}//初始化if (o instanceof InitializingBean){((InitializingBean) o).afterPropertiesSet();}//AOPfor (BeanPostProcessor b: BeanPostProcessorList){//初始化后的操作b.postProcessAfterInitialization(o,beanName);}return o;}

在ceatebean方法
初始化前,初始化,初始化后

   //初始化后for (BeanPostProcessor b: BeanPostProcessorList){b.postProcessBeforeInitialization(o,beanName);}//初始化if (o instanceof InitializingBean){((InitializingBean) o).afterPropertiesSet();}//初始化后for (BeanPostProcessor b: BeanPostProcessorList){b.postProcessAfterInitialization(o,beanName);}

26.wzpBeanPostProcessor的主要功能是AOP,怎么AOP呢,这里用的是动态代理,还要创建一个接口UserInterface

package org.example.spring;public interface UserInterface {void test();
}

服务类再去实现这个接口

@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean , UserInterface {@AutoWiredprivate OrderService orderService;public void test(){System.out.println("hello AOP");}@Overridepublic void afterPropertiesSet() {System.out.println("初始化");}
}

27.在wzpBeanPostProcessor中去完成AOP,比如说初始化后的postProcessAfterInitialization方法中,做AOP,要针对哪个bean,用if判断:

package org.example.spring;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;@Component("wzpBeanPostProcessor")
public class wzpBeanPostProcessor  implements  BeanPostProcessor{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (beanName.equals("UserService")) {Object proxyInstance = Proxy.newProxyInstance(wzpBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//执行AOP的逻辑System.out.println("hello  AOP逻辑在此");//执行完了AOP的操作,执行原来的切点方法return method.invoke(bean,args);}});return proxyInstance;}return bean;}
}

在createbean方法中也要修改,因为要接收代理对象

      //初始化后for (BeanPostProcessor b: BeanPostProcessorList){o=  b.postProcessBeforeInitialization(o,beanName);}//初始化if (o instanceof InitializingBean){((InitializingBean) o).afterPropertiesSet();}//初始化后for (BeanPostProcessor b: BeanPostProcessorList){o= b.postProcessAfterInitialization(o,beanName);}

28.实现Aware接口

在 Spring 中,BeanNameAware 接口是一个回调接口,它提供了一个用于设置 Bean 名称的方法。当一个 Bean 实现了 BeanNameAware 接口时,在该 Bean 实例被实例化后,Spring 容器会调用 setBeanName 方法,并将该 Bean 在 Spring 容器中的名称作为参数传递进去。

创建一个BeanNameAware接口:


public interface BeanNameAware {void setBeanName(String name);
}

在服务类中实现接口:

package org.example.wzp.service;import org.example.spring.*;@Component("UserService")
@Scope("singleton")
public class UserService implements InitializingBean , UserInterface ,BeanNameAware {@AutoWiredprivate OrderService orderService;public void test(){System.out.println("hello AOP");}@Overridepublic void afterPropertiesSet() {System.out.println("初始化");}private String beanName;@Overridepublic void setBeanName(String name) {this.beanName=name;}
}

在createbean函数中:在初始化之前

  //Aware接口if (o instanceof BeanNameAware){((BeanNameAware) o).setBeanName(beanName);}//初始化前for (BeanPostProcessor b: BeanPostProcessorList){o=  b.postProcessBeforeInitialization(o,beanName);}//初始化if (o instanceof InitializingBean){((InitializingBean) o).afterPropertiesSet();}//初始化后for (BeanPostProcessor b: BeanPostProcessorList){o= b.postProcessAfterInitialization(o,beanName);}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

泰迪智能科技携手韩山师范学院“企业微专业合作办学招生宣讲”圆满结束

为进一步深化校企合作&#xff0c;落实高校应用型人才培养。2024年4月11日&#xff0c;泰迪智能科技携手韩山师范学院开展企业微专业合作办学招生宣讲会在韩山师范学院顺利举行&#xff0c;本次宣讲会旨在与韩山师范学院学子深入讲解数字经济时代下的企业用工需求&#xff0c;着…

升级win11后无线鼠标失灵,win11鼠标用不了

鼠标失灵是常见的设备故障问题&#xff0c;今天带来相关的解决方法&#xff0c;本文主要是针对升级win11后无线鼠标失灵的处理方法。不少小伙伴在使用电脑的过程中&#xff0c;都遇到过鼠标移动缓慢或者动不了的情况&#xff0c;升级到win11系统的小伙伴也不例外。一般刚升级新…

c# 服务创建

服务 创建服务 编写服务 可以对server1.cs重新命名&#xff0c;点击你的server按F7进入代码编辑模式&#xff0c;编写脚本 双击你的server.cs右击空白位置&#xff0c;添加安装程序&#xff0c;此时会生成“serviceInstaller1”及“serviceProcessInstaller1” 后续可以点击P…

Five86-1 靶机实战

Nmap: 1.存活探测&#xff1a; nmap -sn 192.168.20.1/24 2.端口探测&#xff1a; nmap -sS -p- 192.168.20.131 3.服务探测&#xff1a; nmap -sVC -p 22,80,10000 -O --version-all 192.168.20.131 这里发现 10000 端口也是http服务。 服务漏扫&#xff1a; nmap -p 2…

Shell——执行方式详解

一.什么是shell Shell 是一个计算机程序&#xff0c;它提供了用户与操作系统内核之间的交互界面。它接受来自用户或其他程序的命令&#xff0c;并将其转换为操作系统能理解的形式&#xff0c;然后执行这些命令并将结果返回给用户或程序。 Shell 在操作系统中扮演着重要的角色…

Proxmox VE 实现批量增加多网络

前言 实现批量创建多网络&#xff0c;更改主机名称&#xff0c;hosts解析 初始化网卡&#xff0c;主机名称&#xff0c;hosts解析&#xff0c;重启网卡 我的主机六个网卡&#xff0c;使用的有四个网卡&#xff0c;以下一键创建和初始化主机名称我是以硬件的SN号最为主机的名…

[ C++ ] STL---map与set的使用指南

目录 关联式容器 键值对 set简介 set的常用接口 构造函数 set的迭代器 set的容量 修改相关接口 find()函数 insert()函数 erase()函数 clear()函数 count函数 lower_bound()函数 upper_bound()函数 multiset简介 map简介 map的常用接口 构造函数 map的迭代…

BK9524 BEKEN博通 无线麦克风接收芯片 提供配置工具软件

BK9524 系列 无线麦克风跳频芯片 24bit/48KHz 数字无线传输 2.5 毫秒的传输延迟 数字加密/绝无串音 无线空中对码/发射跳频/接收自动跟踪 免软件开发的 TURN-KEY 方案 接收芯片 BK9524 特点&#xff1a; 1. 接收灵敏度&#xff1a;-96 dBm(V 段)&#xff1b; -94 dBm (…

《深入Linux内核架构》第2章 进程管理和调度 (6)

目录 2.8 调度器增强 2.8.1 SMP调度 2.8.2 调度域和控制组 2.8.3 内核抢占和低延迟相关工作 2.9 小结 本专栏文章将有70篇左右&#xff0c;欢迎关注&#xff0c;订阅后续文章。 2.8 调度器增强 2.8.1 SMP调度 进程迁移&#xff1a; 含义&#xff1a;把进程从一个CPU就绪队…

BCLinux8U6系统基线加固致无法su的问题分析

本文对BCLinux8U6系统进行基线加固致无法su的问题分析。 一、问题现象 对BCLinux8U6系统进行基线加固&#xff0c;su切换用户失败&#xff0c;报错信息如下&#xff1a; [ABCDlocalhost ~]$ su - 密码&#xff1a; su: 模块未知 二、问题分析 1、错误排查 出错前&#xf…

CubelMX点灯

工程配置 开发板led引脚图 工程io配置 配置PB5 为输出 配置 PE5 为输出 时钟配置 写测试代码 配置工程&#xff0c;下载运行。 参考链接 STM32入门教程-1.点灯_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1dC41147eL/?spm_id_from333.788&vd_sourcee821a225c7b…

为什么需要网络切片?

网络切片是电信领域的一个突破性概念&#xff0c;它允许将物理网络基础设施划分为多个虚拟网络&#xff0c;称为切片。每个切片作为一个独立的网络运行&#xff0c;拥有自己的专用资源和定制的特性&#xff0c;满足不同应用、行业或用户的特定需求。 将网络切片视为在共享物理…