Dubbo系列-SPI原理
Dubbo SPI
DubboSPI贯穿在整个Dubbo的代码中,所以很有必要详细了解SPI的原理。
关于Spring SPI的使用
SpringFactoriesLoader
org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}
}
上述代码就是从META-INF/spring.factories
中获取我们需要的配置信息,spring.factories
的内容大致长这样
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
但是他比JAVA SPI更好的点在于不会一次加载所有的类,而是根据Key进行加载
到之后会按照我们从配置文件中获取的结果,来装配对应的bean,本文不赘述spring的spi原理
关于JAVA SPI
了解 Dubbo 里面的 SPI 机制之前,我们先了解下 Java 提供的 SPI(service provider interface)机制,SPI 是 JDK 内置的一种服务提供发现机制。
目前市面上有很多框架都是用它来做服务的扩展发现。
简单来说,它是一种动态替换发现的机制。
举个简单 的例子,我们想在运行时动态给它添加实现,你只需要添加一个实现,然后把新的实现描述给 JDK 知道就行了。大家耳熟能详的如 JDBC、日志框架都有用到。
SPI的标准
- 在classpath下创建一个目录,目录名称必须是
META-INF/service
- 在该目录下创建一个 properties 文件,该文件需要满足以下几个条件
- 文件名必须是扩展的接口的全路径名称
- 文件内部描述的是该扩展接口的所有实现类
- 文件的编码格式是 UTF-8
- 通过
java.util.ServiceLoader
的加载机制来发现
SPI的实际应用
SPI很多地方都在使用,最常用的就是JDBC驱动
JDK 本身提供了数据访问的 api。
在 java.sql 这个包里面
我们在连接数据库的时候,一定需要用到 java.sql.Driver 如下
java.sql.DriverManager#getConnection(String, Properties, Class<?>)
Connection con = aDriver.driver.connect(url, info);
因为我们在实际应用中用的比较多的是 mysql,所以我们去 mysql 的包里面看到一个如下的目录结构
这个文件里面写的就是 mysql 的驱动实现。文件内容为com.mysql.cj.jdbc.Driver
通过 SPI 机制把java.sql.Driver
和 mysql 的驱动
做了集成。
这样就达到了各个数据库厂商自己去实现数据库连接,jdk 本身不关心你怎么实现。
那JDBC是如何加载的呢
java.sql.DriverManager#loadInitialDrivers
在这个方法中通过
private static void loadInitialDrivers() {String drivers;try {drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {public String run() {return System.getProperty("jdbc.drivers");}});} catch (Exception ex) {drivers = null;}AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();try{while(driversIterator.hasNext()) {driversIterator.next();}} catch(Throwable t) {// Do nothing}return null;}});println("DriverManager.initialize: jdbc.drivers = " + drivers);if (drivers == null || drivers.equals("")) {return;}String[] driversList = drivers.split(":");println("number of Drivers:" + driversList.length);for (String aDriver : driversList) {try {println("DriverManager.Initialize: loading " + aDriver);Class.forName(aDriver, true,ClassLoader.getSystemClassLoader());} catch (Exception ex) {println("DriverManager.Initialize: load failed: " + ex);}}}
此方法来获取jar包中获取到的driver从而加载到类加载器中等待使用
SPI的缺点
- 从上述代码可以看到 JDK 标准的 SPI 会一次性加载实例化扩展点的所有实现,什么意思呢?
- 就是如果你在
META-INF/service
下的文件里面加了 N 个实现类,那么 JDK 启动的时候都会一次性全部加载。那么如果有的扩展点实现初始化很耗时或者如果有些实现类并没有用到, 那么会很浪费资源
- 就是如果你在
- 如果扩展点加载失败,会导致调用方报错,而且这个错误很难定位
Dubbo优化后的SPI
基于DubboSPI实现自己的扩展
参考文档地址
org.apache.dubbo.common.extension.ExtensionLoader#loadExtensionClasses
Dubbo 的 SPI 扩展机制,有两个规则
- 需要在 resource 目录以下其中一个目录中创建一个文件
META-INF/dubbo
META-INF/dubbo/internal
META-INF/services
- 文件名称和接口名称保持一致,文件内容和 SPI 有差异,内容是 KEY 对应 Value
Dubbo 针对的扩展点非常多
协议、调用拦截、引用监听、暴露扩展等几乎所有的功能都能应用自己的扩展
实现一个自己的扩展点
在目录resources/META-INF/dubbo
下创建文件org.apache.dubbo.rpc.Protocol
文件内容为
myProtocol=com.zzjson.dubbo.consumer.MyProtocol
public class MyProtocol implements Protocol {@Overridepublic int getDefaultPort() {return 9527;}
。。。
}
测试类
public static void main(String[] args) {ExtensionLoader<Protocol> extensionLoader = ExtensionLoader.getExtensionLoader(Protocol.class);Protocol myProtocol = extensionLoader.getExtension("myProtocol");System.out.println(9527 == myProtocol.getDefaultPort());
}
发现成功的获取到了自己定义的扩展点
总的来说,思路和 SPI 是差不多。都是基于约定的路径下制定配置文件。通过配置的方式轻松实现功能的扩展。
我们的猜想是,一定有一个地方通过读取指定路径下的所有文件进行 load。然后讲对应的结果保存到一个 map 中,key 对应为 名称,value 对应为实现类。那么这个实现,一定就在 ExtensionLoader 中了。
接下来我们就可以基于这个猜想去看看代码的实现。
Dubbo扩展点原理
大家要思考一个问题,所谓的扩展点,就是通过指定目录下配置一个对应接口的实现类,然后程序会进行查找和解析,找到对应的扩展点。那么这里就涉及到两个问题
- 怎么解析
- 被加载的类如何存储和使用
从一行代码入手
private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).get("myProtocol");
-
SPI的类都使用了注解
@SPI
-
@SPI("dubbo") public interface Protocol{}
ExtensionLoader#getExtensionLoader
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {if (type == null) {throw new IllegalArgumentException("Extension type == null");}if (!type.isInterface()) {throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");}if (!withExtensionAnnotation(type)) {throw new IllegalArgumentException("Extension type (" + type +") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");}ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);if (loader == null) {EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);}return loader;
}
对Extension做了缓存,存储在了ConcurrentMap
中
实例化ExtensionLoader
private ExtensionLoader(Class<?> type) {this.type = type;objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
如果当前的 type=ExtensionFactory,那么 objectFactory=null,
否则会创建一个自适应扩展点给到 objectFacotry,自适应扩展点是什么我们会在下文解释
ExtensionLoader#getExtension
public T getExtension(String name) {if (StringUtils.isEmpty(name)) {throw new IllegalArgumentException("Extension name == null");}if ("true".equals(name)) {//如果 name=true,表示返回一个默认的扩展点return getDefaultExtension();}//缓存一下,如果实例已经加载过了,直接从缓存读取final Holder<Object> holder = getOrCreateHolder(name);Object instance = holder.get();if (instance == null) {synchronized (holder) {instance = holder.get();if (instance == null) {//根据名称创建实例instance = createExtension(name);holder.set(instance);}}}return (T) instance;
}
这个方法就是根据一个名字来获得一个对应类的实例,所以我们来猜想一下,回想一下前面咱们配置的自定义协议,name 实际 上就是 myprotocol,而返回的实现类应该就是 MyProtocol。
defaultExtension就是我们在@SPI
注解中默认的值
@SPI("spring")
public interface Container {}
ExtensionLoader#createExtension
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);private T createExtension(String name) {Class<?> clazz = getExtensionClasses().get(name);if (clazz == null) {throw findException(name);}try {T instance = (T) EXTENSION_INSTANCES.get(clazz);if (instance == null) {EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());instance = (T) EXTENSION_INSTANCES.get(clazz);}injectExtension(instance);Set<Class<?>> wrapperClasses = cachedWrapperClasses;if (CollectionUtils.isNotEmpty(wrapperClasses)) {for (Class<?> wrapperClass : wrapperClasses) {instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));}}initExtension(instance);return instance;} catch (Throwable t) {throw new IllegalStateException("Extension instance (name: " + name + ", class: " +type + ") couldn't be instantiated: " + t.getMessage(), t);}
}
ExtensionLoader#getExtensionClass
private Class<?> getExtensionClass(String name) {if (type == null) {throw new IllegalArgumentException("Extension type == null");}if (name == null) {throw new IllegalArgumentException("Extension name == null");}return getExtensionClasses().get(name);
}
这一块都是判断参数是否正确,继续查找重载空构造方法
ExtensionLoader#getExtensionClasses
private Map<String, Class<?>> getExtensionClasses() {Map<String, Class<?>> classes = cachedClasses.get();if (classes == null) {synchronized (cachedClasses) {classes = cachedClasses.get();if (classes == null) {classes = loadExtensionClasses();cachedClasses.set(classes);}}}return classes;
}
ExtensionLoader#loadExtensionClasses
private Map<String, Class<?>> loadExtensionClasses() {cacheDefaultExtensionName();Map<String, Class<?>> extensionClasses = new HashMap<>();for (LoadingStrategy strategy : strategies) {loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());}return extensionClasses;
}
这个方法,会查找指定目录
/META-INF/dubbo
META-INF/dubbo/
META-INF/dubbo/internal/
中对应的 type上文中的 Protocol 的 properties 文件,然后扫描这个文件下的所有配置信息。
然后保存到一个 HashMap中
- key=对应 protocol 文件中配置的 myprotocol
- value=对应配置的类的实例
依赖注入-ExtensionLoader#InjectExtension
private T injectExtension(T instance) {if (objectFactory == null) {return instance;}try {for (Method method : instance.getClass().getMethods()) {if (!isSetter(method)) {continue;}if (method.getAnnotation(DisableInject.class) != null) {continue;}//获得方法的参数,这个参数必须是一个对象类型并且是一个扩展点Class<?> pt = method.getParameterTypes()[0];if (ReflectUtils.isPrimitives(pt)) {continue;}try {String property = getSetterProperty(method);Object object = objectFactory.getExtension(pt, property);if (object != null) {//调用 set 方法进行赋值method.invoke(instance, object);}} catch (Exception e) {logger.error("Failed to inject via method " + method.getName()+ " of interface " + type.getName() + ": " + e.getMessage(), e);}}} catch (Exception e) {logger.error(e.getMessage(), e);}return instance;
}
这个方法是用来实现依赖注入的,如果被加载的实例中,有成员属性本身也是一个扩展点,并且没有被标识DisableInject
则会通过 set 方法进行注入。
依赖注入也是dubbo一个更加强大的点
Adaptive自适应扩展点
自适应扩展点
有些拓展并不想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载。这听起来有些矛盾。拓展未被加载,那么拓展方法就无法被调用(静态方法除外)。拓展方法未被调用,拓展就无法被加载。对于这个矛盾的问题,Dubbo 通过自适应拓展机制很好的解决了。
什么叫自适应扩展点呢?
我们先演示一个例子,在下面这个例子中,我们传入一个 Compiler 接口,它会返回一个 AdaptiveCompiler。
这个就叫自适应。
Compiler compiler=ExtensionLoader.getExtensionLoader(Compiler.class).getAdaptiveExtension(); System.out.println(compiler.getClass());
它是怎么实现的呢?
我们根据返回的 AdaptiveCompiler 这个类,看到这个类上面有一个注解@Adaptive。 这个就是一个自适应 扩展点的标识。
@Adaptive
public class AdaptiveCompiler implements Compiler {}
它可以修饰在类上,也可以修饰在方法上面。这两者有什么区别呢?
简单来说,放在类上,说明当前类是一个确定的自适应扩展点的类。如果是放在方法级别,那么需要生成一个动态字节码,来进行转发。
比如拿 Protocol 这个接口来说,它里面定义了export和refer 两个抽象方法,这两个方法分别带有@Adaptive
的标识,标识是 一个自适应方法。
@SPI("dubbo")
public interface Protocol {@Adaptive<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;@Adaptive<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}
我们知道 Protocol 是一个通信协议的接口,具体有多种实现,那么这个时候选择哪一种呢?
取决于我们在使用 dubbo 的时候所配置的协议名称。
而这里的方法层面的 Adaptive 就决定了当前这个方法会采用何种协议来发布服务。
private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
ExtensionLoader#getAdaptiveExtension
public T getAdaptiveExtension() {Object instance = cachedAdaptiveInstance.get();if (instance == null) {if (createAdaptiveInstanceError != null) {throw new IllegalStateException("Failed to create adaptive instance: " +createAdaptiveInstanceError.toString(),createAdaptiveInstanceError);}synchronized (cachedAdaptiveInstance) {instance = cachedAdaptiveInstance.get();if (instance == null) {try {instance = createAdaptiveExtension();cachedAdaptiveInstance.set(instance);} catch (Throwable t) {createAdaptiveInstanceError = t;throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);}}}}return (T) instance;
}
ExtensionLoader#createAdaptiveExtension
private T createAdaptiveExtension() {try {return injectExtension((T) getAdaptiveExtensionClass().newInstance());} catch (Exception e) {throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);}
}
这个方法中做两个事情
- 获得一个自适应扩展点实例
- 实现依赖注入
ExtensionLoader#getAdaptiveExtensionClass
private Class<?> getAdaptiveExtensionClass() {getExtensionClasses();if (cachedAdaptiveClass != null) {return cachedAdaptiveClass;}return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
getExtensionClasses()这个方法在上文中已经讲过了,会加载当前传入的类型的所有扩展点,保存在一个 hashmap 中
cachedAdaptiveClass, Adaptive 可以放在两个位置,一个是类级别,一个是方法级别。
那么这个 cachedAdaptiveClass很显然,就是放在类级别的 Adaptive,
org.apache.dubbo.common.extension.ExtensionLoader#loadClass
if (clazz.isAnnotationPresent(Adaptive.class)) {cacheAdaptiveClass(clazz);
}
private void cacheAdaptiveClass(Class<?> clazz) {if (cachedAdaptiveClass == null) {cachedAdaptiveClass = clazz;} else if (!cachedAdaptiveClass.equals(clazz)) {throw new IllegalStateException("More than 1 adaptive class found: "+ cachedAdaptiveClass.getName()+ ", " + clazz.getName());}
}
在加载完之后如果这个类有@Adaptive 标识,则会赋值给 cachedAdaptiveClass如果 cachedAdaptiveClass 不存在,dubbo 会动态生成一个代理类 Protocol$Adaptive. 前面的名字 protocol 是根据当前 ExtensionLoader 所加载的扩展点来定义的
ExtensionLoader#createAdaptiveExtensionClass
private Class<?> createAdaptiveExtensionClass() {String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();ClassLoader classLoader = findClassLoader();org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();return compiler.compile(code, classLoader);
}
动态生成字节码,然后进行动态加载。那么这个时候返回的 class,如果加载的是 Protocol.class, 应该是 Protocol$Adaptive 这个 cachedDefaultName 实际上就是扩展点接口的@SPI 注解对应的名字,如果此时加载的是 Protocol.class,那么 cachedDefaultName=dubbo
Protocol$Adaptive
通过debug获取动态生成的代理类
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {public void destroy() {throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");}public int getDefaultPort() {throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");}public java.util.List getServers() {throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");}public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {if (arg0 == null) {throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");}if (arg0.getUrl() == null) {throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");}org.apache.dubbo.common.URL url = arg0.getUrl();String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null) {throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");}org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);return extension.export(arg0);}public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {if (arg1 == null) {throw new IllegalArgumentException("url == null");}org.apache.dubbo.common.URL url = arg1;String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null) {throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");}org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);return extension.refer(arg0, arg1);}
}
关于ExtensionFactory
在上述实例化ExtensionLoader的地方我们发现有一个实例化ExtensionFactory的地方
private ExtensionLoader(Class<?> type) {this.type = type;objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
然后通过 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()去获得一个自适应的扩展点,进 入 ExtensionFactory 这个接口中,可以看到它是一个扩展点,并且有一个自己实现的自适应扩展点 AdaptiveExtensionFactory;
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {private final List<ExtensionFactory> factories;public AdaptiveExtensionFactory() {ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();for (String name : loader.getSupportedExtensions()) {list.add(loader.getExtension(name));}factories = Collections.unmodifiableList(list);}@Overridepublic <T> T getExtension(Class<T> type, String name) {for (ExtensionFactory factory : factories) {T extension = factory.getExtension(type, name);if (extension != null) {return extension;}}return null;}}
他会从配置文件中读取对应的extensionfactory找到一个就返回了
Activate自动激活扩展点
自动激活扩展点,有点类似 springboot 的时候用到的 conditional,根据条件进行自动激活。
但是这里设计的初衷是,对 于一个类会加载多个扩展点的实现,这个时候可以通过自动激活扩展点进行动态加载, 从而简化配置我们的配置工作 @Activate 提供了一些配置来允许我们配置加载条件,比如 group 过滤,比如 key 过滤。
举个例子,我们可以看看org.apache.dubbo.Filter
这个类,它有非常多的实现,比如说 CacheFilter,这个缓存过滤器,配置信息 如下
group 表示客户端和和服务端都会加载,value 表示 url 中有 cache_key 的时候
@Activate(group = {CONSUMER, PROVIDER}, value = CACHE_KEY)
public class CacheFilter implements Filter {}
ExtensionLoader#getActivateExtension(URL, String[], String)
public List<T> getActivateExtension(URL url, String[] values, String group) {List<T> activateExtensions = new ArrayList<>();List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {getExtensionClasses();for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {String name = entry.getKey();Object activate = entry.getValue();String[] activateGroup, activateValue;if (activate instanceof Activate) {activateGroup = ((Activate) activate).group();activateValue = ((Activate) activate).value();} else if (activate instanceof com.alibaba.dubbo.common.extension.Activate) {activateGroup = ((com.alibaba.dubbo.common.extension.Activate) activate).group();activateValue = ((com.alibaba.dubbo.common.extension.Activate) activate).value();} else {continue;}if (isMatchGroup(group, activateGroup)&& !names.contains(name)&& !names.contains(REMOVE_VALUE_PREFIX + name)&& isActive(activateValue, url)) {activateExtensions.add(getExtension(name));}}activateExtensions.sort(ActivateComparator.COMPARATOR);}List<T> loadedExtensions = new ArrayList<>();for (int i = 0; i < names.size(); i++) {String name = names.get(i);if (!name.startsWith(REMOVE_VALUE_PREFIX)&& !names.contains(REMOVE_VALUE_PREFIX + name)) {if (DEFAULT_KEY.equals(name)) {if (!loadedExtensions.isEmpty()) {activateExtensions.addAll(0, loadedExtensions);loadedExtensions.clear();}} else {loadedExtensions.add(getExtension(name));}}}if (!loadedExtensions.isEmpty()) {activateExtensions.addAll(loadedExtensions);}return activateExtensions;
}
从代码中可以看出来,其会对标记了Activate
注解的类进行判断和排序满足条件的才能被使用
public class AdaptiveBootStrap {public static void main(String[] args) {ExtensionLoader<Filter> loader = ExtensionLoader.getExtensionLoader(Filter.class);URL url = new URL("", "", 0);url = url.addParameter("cache", "cache");//有和没有的区别List<Filter> filters = loader.getActivateExtension(url, "cache");System.out.println(filters.size());}
}
当前文档中当我们的url中有满足cacheFilter中的key的时候则会把对应的filter加载出来
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 创新实训记录16--工作总结
工作总结工作展示(ppt)技术难点 工作展示(ppt)总结技术难点 1 django整体界面的设计与实现 2.pyecharts 动态可视化的融合展示 3.实现前端与后台的交互 4.colab的使用 5.bert模型的理解...
2024/4/20 3:48:23 - 【比特币】将在2020年以28.8万美元的牛市运行
比特币S2FX价格模型的最新更新显示,7月正按照长期看涨轨迹持续所要求的开始。市场新闻 新的库存流量数据证实,比特币(BTC)可能难以达到10.000美元,但其进展是正确的。 从7月1日开始,库存到流量模型创建者PlanB对他的模型进行了新的更新,显示比特币的行为完全符合其看涨历史…...
2024/4/19 21:20:59 - 线性系统实验:化学方程式配平 and 天体轨道参数估计
线性系统消元法高斯消元法高斯-约旦消元法工程应用:化学方程式配平逆矩阵求解解的结构超定方程组近似估值工程应用:天体轨道参数估计 消元法 线性系统,在高中称为 多元一次方程组,因为在线性代数里,我们把矩阵看成系统,而这些方程组的未知数都只有一次,所以就了线性系统…...
2024/4/17 21:35:07 - Linux下redis的安装及用法
Linux下redis的安装及用法 下面介绍在Linux环境下,Redis的安装与部署 1、在安装redis之前先安装C++编译环境,查看目前服务器上gcc的版本:gcc -v, 如果Linux系统没有安装gcc编译器,会提示“Command not found”;如果提示命令找不到,则表明没有安装; 或者更新版本,不然后…...
2024/4/18 9:31:31 - 2020.7.1总结
前端知识: API: 判断是否为空: $.common.isEmpty() modal框: $.common.alertError() 弹层组件:layer layer.open({ title:false, type:1, closeBth:true, shadeClose:true,//阴影区域关闭 area:[‘auto’,‘atuo’]//宽,高 }) 以下是一些参数截图:layer组件:web弹层组…...
2024/5/4 2:24:33 - 企业人力资源管理项目SSH+EXTJS+MySQL整合开发源码分享
企业人力资源管理项目,是SSH+EXT+MySQL+MD5...... 功能有:会话过滤、MD5加密、文件上传、权限设置、报表统计......运行环境jdk7tomcat7mysqlIntelliJ IDEA 项目技术(必填)springstrutshibernate 项目截图运行截图关注点赞之后,私信关键字【源码】即可免费获取~...
2024/4/20 16:13:28 - LittleVGL 源码分析--src/lv_misc/lv_log.h
这是log配置信息:/*================* Log settings 日志设置*===============*//*1: Enable the log module 启用日志模块 */ #define LV_USE_LOG 1 #if LV_USE_LOG /* How important log should be added:* LV_LOG_LEVEL_TRACE A lot of logs to give detailed…...
2024/4/18 14:27:02 - 转载:setsockopt()函数功能介绍
文章来源: https://www.cnblogs.com/eeexu123/p/5275783.html setsockopt()函数功能介绍 功能描述:获取或者设置与某个套接字关联的选 项。选项可能存在于多层协议中,它们总会出现在最上面的套接字层。当操作套接字选项时,选项位于的层和选项的名称必须给出。为了操作套接字…...
2024/4/23 18:49:33 - springboot 读取配置文件为HashMap
1.配置文件样例:abc.xxx.kk=zzz,yyyyabc.zzz.aa=rrrabc.zzz.bb=rrrabc.zzz.cc=rrrabc.yyy.aa=rrabc.yyy.bb=rrabc.yyy.cc=rr2.java 代码:@Configurationpublic xxconfig{@value("#{${abc.xxx.kk}.split(,).}")public List<String> list;@Beanpublic Map<…...
2024/4/16 16:36:50 - @options
1.作用: (1)能够设置缓存时间; (2)能够为对象生成自增的主键值;2.应用场景: (1).插入时使用,eg:插入一件商品并返回主键值//useGeneratedKeys :默认 false ,作用:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。//keyProperty、…...
2024/4/16 16:35:54 - Kubernetes集群——(k8s)service(二)+ingress+nodprot实现负载均衡+daemonset实现会话保持+TLS加密认证
一、ingress简介 一种全局的、为了代理不同后端 Service 而设置的负载均衡服务,就是 Kubernetes 里的 Ingress 服务。 • Ingress由两部分组成:Ingress controller和Ingress服务。 • Ingress Controller 会根据你定义的 Ingress 对象,提供对应的代理能力。业界常用的各 种反…...
2024/4/16 16:35:59 - 牛客网 编程题——C++求最小公倍数 《完整代码加分析》
一,题目描述 正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。 输入描述: 输入两个正整数A和B。 输出描述: 输出A和B的最小公倍数。 示例1 输入 5 7输出 35二,程序分析 1.最小公倍数 = 两数之积除以最大公约数 2.即…...
2024/4/20 10:42:39 - 初探numpy——广播和数组操作函数
广播和数组操作函数numpy广播(Broadcast)numpy数组操作函数修改数组形状numpy.reshape()numpy.ndarray.flatnumpy.ndarray.flatten和numpy.ravel翻转数组transpose和ndarray.Tnumpy.swapaxes numpy广播(Broadcast) 若数组a,b形状相同,即a.shape==b.shape,那么a+b,a*b的结…...
2024/4/16 16:35:28 - P1009 阶乘之和
展开 题目描述 用高精度计算出S=1!+2!+3!+…+n! (n≤50) 其中“!”表示阶乘,例如:5!=54321。 输入格式 一个正整数N。 输出格式 一个正整数S,表示计算结果。 #include <iostream> #include <string> #include <algorithm> #include <queue> #includ…...
2024/4/18 19:02:37 - 每日一题Day8
1.java中关于内存回收的正确说法是(B)A 程序员必须创建一个线程来释放内存B 内存回收程序负责释放无用内存 C 内存回收程序允许程序员直接释放内存 D 内存回收程序可以在指定的时间释放内存对象解析:A:垃圾回收程序是一般是在堆上分配空间不够的时候会自己进行一次GC,程序…...
2024/4/16 16:36:04 - Sqoop安装以及指令学习 ----------语句学习一条龙
Sqoop:Sqoop介绍Sqoop安装Sqoop操作连接mysqlHadoop拉取全量导入:按sql语句导入: Sqoop介绍Sqoop是一个用于在Hadoop和关系型数据库之间传输数据的工具将数据从RDBMS导入到HDFS RDBMS:HDFS、Hive、Hbase 从HDFS导出数据到RDBMS 使用MapReduce导入和导出数据,提供并行操作和容…...
2024/4/16 16:36:24 - IPFS周报-95:你是如何探索IPFS生态的?官方正在调查
协议实验室 编制 IPFS原力区 编译星际文件系统(IPFS)是一种新的超媒体分发协议,通过内容和身份进行寻址。IPFS支持创建完全分布式应用程序,它的目的是使网络更快、更安全、更开放。01、go-ipfs 0.6.0上周晚些时候,go-ipfs 0.6.0发布,带来了QUIC传输、噪音安全传输、定制…...
2024/4/16 16:35:59 - 大众流行编程语言有哪些 该选择哪一个来入门
大众流行编程语言有哪些?该选择哪一个来入门?现如今,互联网时代已经是风生水起,IT技术人才更是层出不穷。但学习在精不在多,总要有一方面精通才是自己的资本。面对众多的编程语言,Java、C语言、C++、Python等编程,该选择哪一个作为自己的精通点呢? 我觉得从语言特征上太…...
2024/4/16 16:36:55 - NLP-contextualized representations-task04
基于上下文的词嵌入方法1 Word2Vec,Glove & Fastext2 一词多义2.1 ELMO2.2 BERT2.3 GPT3 小结 1 Word2Vec,Glove & Fastext 回顾之前内容,对于词如何转为数学表示,最基础的是词的编码,即one-hot编码,这样可以将词转为计算机可以处理的对象,但缺点是完全丢失了词本…...
2024/5/4 1:24:03 - 前端基础——CSS 列表、背景、盒子模型、浮动、定位和z-index
列表样式可以更改列表中点的样式或者去掉点 复习之前内容#nav{width: 300px;}.title{font-size: 18px;font-weight: bold;text-indent: 1em;line-height: 35px;}ul li{height: 30px;/*列表的点none:去除 circle:空心圆decimal:数字123. square正方形*/list-style: none;text…...
2024/4/7 0:23:46
最新文章
- sql注入工具-sqlmap
介绍: sqlmap是一款开源的自动化SQL注入工具,用于自动化检测和利用Web应用程序中的SQL注入漏洞。它具有强大的参数化查询和自定义注入脚本的功能,可以通过检测和利用SQL注入漏洞来获取数据库的敏感信息,如用户名、密码和其他重要…...
2024/5/4 5:14:07 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - Django实现的登录注册功能
1 前言 在Web开发中,用户登录和注册是最基本且必不可少的功能。Django,作为一个高级的Python Web框架,为我们提供了强大的工具和库来快速实现这些功能。下面,我将详细介绍如何使用Django来实现用户登录和注册功能。 2 功能介绍 …...
2024/5/1 13:23:09 - 【VTKExamples::Meshes】第七期 TableBasedClipDataSetWithPolyData
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例TableBasedClipDataSetWithPolyData,并解析接口vtkTableBasedClipDataSet,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你…...
2024/5/1 13:33:21 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/1 17:30:59 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/2 16:16:39 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/29 2:29:43 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/3 23:10:03 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/30 9:43:09 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/2 15:04:34 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/29 20:46:55 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/30 22:21:04 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/1 4:32:01 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/4 2:59:34 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/30 9:42:22 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/2 9:07:46 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/30 9:42:49 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57