SpringBoot事务

Springboot中事务是相对重要的一个部分。也是aop的一个使用场景。我们今天就来一起从源码的角度分析下,事务的整个创建过程。

关于springboot启动过程中的一些加载,很多都是通用的,这块就不再仔细讲述了。这部分可以参看spring boot 加载web容器tomcat流程源码分析和springboot整合mybatis源码分析这两篇文章

关于enhancer生成代理类的过程,可以参看Springboot中注解@Configuration源码分析

代码路径:springboot-transaction

1. 自动加载配置

首先还是读取org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration这个配置类,

方式还是通过springboot启动的时候自动加载配置文件spring-boot-autoconfigure-2.5.2.jar中\META-INF\spring.factories这个文件中key=org.springframework.boot.autoconfigure.EnableAutoConfiguration的值。其中就有org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration这个类。

在加载org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration时,会扫描加载内部类。

这里就会扫描到EnableTransactionManagementConfiguration这个内部类。

@Configuration(proxyBeanMethods = false)@ConditionalOnBean(TransactionManager.class)@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)public static class EnableTransactionManagementConfiguration {@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")public static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)@EnableTransactionManagement(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)public static class CglibAutoProxyConfiguration {}}

同时会扫描JdkDynamicAutoProxyConfiguration,CglibAutoProxyConfiguration这两个类,默认,我们在上下文中没有配置spring.aop.proxy-target-class属性,所以就只会加载CglibAutoProxyConfiguration这个类,继而读取@EnableTransactionManagement(proxyTargetClass = true)注解,继续去加载EnableTransactionManagement注解类上的import注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
//会读取这里的import注解,去加载TransactionManagementConfigurationSelector这个类
public @interface EnableTransactionManagement {......
}

我们看下这个TransactionManagementConfigurationSelector的继承关系

这才是Springboot事务创建流程的正确打开方式(附源码分析!)

可以看到TransactionManagementConfigurationSelector继承了AdviceModeImportSelector这个,间接实现了ImportSelector接口,所以在加载TransactionManagementConfigurationSelector时,会调用ImportSelector接口的这个方法String[] selectImports(AnnotationMetadata importingClassMetadata);这个接口,这个接口当前时在AdviceModeImportSelector这个类中实现的。

我们看看这部分代码

	//这个代码在AdviceModeImportSelector类中public final String[] selectImports(AnnotationMetadata importingClassMetadata) {Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);//这句代码是获取AdviceModeImportSelector子类的泛型参数。我们这里获取到的是EnableTransactionManagementAssert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);//这句是从当前类的导入类中获取泛型参数注解的对象,这里获取到的是CglibAutoProxyConfiguration类上@EnableTransactionManagement(proxyTargetClass = true)注解的值if (attributes == null) {throw new IllegalArgumentException(String.format("@%s is not present on importing class '%s' as expected",annType.getSimpleName(), importingClassMetadata.getClassName()));}AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());//这个是获取model属性的值,这个属性有默认值EnableTransactionManagement注解mode的默认值是AdviceMode.PROXYString[] imports = selectImports(adviceMode);//这个代码的实现在TransactionManagementConfigurationSelector类中,这个也比较简单,就是根据adviceMode的值,返回要加载的类的类名,当前这里返回的是new String[] {AutoProxyRegistrar.class.getName(),						ProxyTransactionManagementConfiguration.class.getName()};//后面就会去加载AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个类if (imports == null) {throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);}return imports;}

下面我们看看AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个类的加载

AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,加载时就会调用registerBeanDefinitions。

	//AutoProxyRegistrar的方法//这里的importingClassMetadata可以认为还是CglibAutoProxyConfigurationpublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound = false;Set<String> annTypes = importingClassMetadata.getAnnotationTypes();//这里是获取CglibAutoProxyConfiguration类上的注解//这里就比较简单了,依次获取CglibAutoProxyConfiguration类上的注解,查看属性mode和proxyTargetClassfor (String annType : annTypes) {AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);if (candidate == null) {continue;}Object mode = candidate.get("mode");Object proxyTargetClass = candidate.get("proxyTargetClass");if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&Boolean.class == proxyTargetClass.getClass()) {candidateFound = true;if (mode == AdviceMode.PROXY) {//最终会走到这里AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);//这里就不进去了,这个会在registry中添加InfrastructureAdvisorAutoProxyCreator.class这个类的beanDefinitionif ((Boolean) proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);//这里是添加了属性("proxyTargetClass", Boolean.TRUE),最终生成的InfrastructureAdvisorAutoProxyCreator的属性进行设置return;}}}}......}

ProxyTransactionManagementConfiguration这个类是一个普通的Configuration配置类,在加载它的过程中同样会扫描到它里面的beanmethod进行加载,这里面的几个也都比较重要,我们看看它的源码

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//会扫描它内部的beanMethod,进行加载,关于这beanmethod的所用,这里就不展看说了,具体在讲解到事务执行流程的时候再说吧
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//注意:这个方法的两个入参是后面两个beanmethod方法的bean对象public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource);advisor.setAdvice(transactionInterceptor);if (this.enableTx != null) {advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//这个类主要是过滤候选类是否可以被用来事务增强,并返回对应的事务属性对象public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//这个主要就是事务拦截器,事务相关的就会交给它去处理public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource);if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}

到这里,我们看看主要加载的bean都有哪些

  • InfrastructureAdvisorAutoProxyCreator,BeanFactoryTransactionAttributeSourceAdvisor主要是这两个TransactionAttributeSource,TransactionInterceptor这两个注入到了BeanFactoryTransactionAttributeSourceAdvisor这个对象中,就不单独说了,应该可以通过BeanFactoryTransactionAttributeSourceAdvisor这个bean对象获取到

2. InfrastructureAdvisorAutoProxyCreator类

我们看看InfrastructureAdvisorAutoProxyCreator的继承关系

这才是Springboot事务创建流程的正确打开方式(附源码分析!)

这个类的继承关系是比较复杂的,我们只挑选我们最关注的来分析吧。

从图上可以看到InfrastructureAdvisorAutoProxyCreator类间接实现了BeanPostProcessor接口,这个接口主要的所用是对每一个bean对象初始化前后做增强。在每一个bean初始化前调用postProcessBeforeInitialization,初始化后调用postProcessAfterInitialization。

注意:这里说的bean初始化前后并不是创建对象前后,这些操作肯定都是在创建对象之后

3.BeanFactoryTransactionAttributeSourceAdvisor类

我们现在看看BeanFactoryTransactionAttributeSourceAdvisor类,首先看下它的继承关系

这才是Springboot事务创建流程的正确打开方式(附源码分析!)

可以看到这个类也实现了Advisor接口,这个接口主要是用来承载Advice,而Advice主要是用来执行作为拦截器来使用的。

同时这个类也实现了PointcutAdvisor,可以返回Pointcut,可以用来筛选哪些方法需要拦截

4.判断bean对象是否需要进行事务增强处理

bean初始化后也会调用到InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization方法(在AbstractAutoProxyCreator这个类中)。继而会调用到wrapIfNecessary这个方法。我们去看看这个方法

	//AbstractAutoProxyCreator类中的方法protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.//看上面的英文注释也能简单明白 aop就是在这里生成的,对应事务其实也是用aop来完成的,我们重点看看这里的代码。//我们的@Transactional注解是在UserServiceImpl这个类上,所以我们就只关注这个类的执行过程就可以了,我们进到这个方法里面去看看Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);//这个specificInterceptors主要是Advisor,这个不为空,说明当前的bean对象,可以被specificInterceptors来进行aop代理,就会进入里面的createProxy进行aop增强if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);//在这里会生成代理类,并返回代理对象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
@Override
@Nullable
//这个方法主要是根据我们传入的bean,查找适用的advice和advisor,如果返回的是空,就说明不需要进行AOP增强,
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {//这句比较简单,主要就是在beanFactory中获取类型是Advisor.class的对应bean,这个也比较简单,就跳进去看了,//我们这里会返回的List中就会只有org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();//这个主要是根据我们传入的bean对象,从candidateAdvisors返回合适的advisor,我们走进去看看List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;
}
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {//我们当前传入的BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor接口的实现,不会走到这里if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}//真正起所用的是在这里,我们继续跳进去看看//canApply返回true,就说明当前的candidate能作用于当前clazz,就需要加到列表,后续生成aop代理的时候需要if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {//PointcutAdvisor 主要是通过getPointcut来获取Pointcut,从目标类上寻找应该被进行aop增强的类和方法PointcutAdvisor pca = (PointcutAdvisor) advisor;//会走到这里面,我们继续进去看看,在这里就是去查找对应类的事务属性(简单来说就是获取方法上的@Transactional的相关属性),如果能获取到这里就会返回true,获取不到就会返回false return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}
}
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");//这个主要是判断类是否有必要pointcut的匹配。//1. 如果类是TransactionalProxy、TransactionManager、PersistenceExceptionTranslator那就不需要后续匹配了直接从if分支里面返回//2.或者要找的类是java.开头的,或者org.springframework.core这个接口,也从这里返回  //我们当前查找的是事务的注解,名字是org.springframework.transaction.annotation.Transactional//我们当前要匹配的类是com.springboot.transaction.service.impl.UserServiceImpl//上面两个条件都不匹配,所以不会进入这个分支,继续向下走if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set<Class<?>> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {//会走到这里,将com.springboot.transaction.service.impl.UserServiceImpl加入到classes中classes.add(ClassUtils.getUserClass(targetClass));}//在这里会将当前类实现的接口com.springboot.transaction.service.UserService也加入进来classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//在下面这里就会去遍历类上的所有方法,查找是否有  @Transactional注解for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) ://会走到下面这个匹配条件,我们进到这个方法去看看methodMatcher.matches(method, targetClass)) {return true;}}}return false;}
//这个方法在TransactionAttributeSourcePointcut,这是一个抽象类
//当前这个类是BeanFactoryTransactionAttributeSourceAdvisor中的内部匿名类,类实例对象名是pointcut@Overridepublic boolean matches(Method method, Class<?> targetClass) {//这个tas就是在初始化BeanFactoryTransactionAttributeSourceAdvisor这个bean时,注入上去的TransactionAttributeSource的beanTransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}
//这个方法在AbstractFallbackTransactionAttributeSource,
//注入上去的TransactionAttributeSource的bean的实际类型是AnnotationTransactionAttributeSource,它继承了AbstractFallbackTransactionAttributeSource
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {if (method.getDeclaringClass() == Object.class) {return null;}// First, see if we have a cached value.//在这里会生成一个缓存的keyObject cacheKey = getCacheKey(method, targetClass);//从缓存中查看对应的事务属性是否存在 ,如果存在就直接返回,我们这里是第一次,就会走到后面的获取部分TransactionAttribute cached = this.attributeCache.get(cacheKey);if (cached != null) {// Value will either be canonical value indicating there is no transaction attribute,// or an actual transaction attribute.if (cached == NULL_TRANSACTION_ATTRIBUTE) {return null;}else {return cached;}}else {// We need to work it out.//在这就是在对应的method上去查看是否有对应Transactional注解,如果有,就封装成TransactionAttribute返回//这个具体也是通过SpringTransactionAnnotationParser.parseTransactionAnnotation方法来完成的,这个比较简单,就不进去了TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);// Put it in the cache.if (txAttr == null) {//如果获取不到,为了避免后续重复查找,也会在这里添加缓存 this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);}else {//我们当前会走到这里,methodIdentification就是类名加方法名的拼接,作为描述String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);if (txAttr instanceof DefaultTransactionAttribute) {DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;dta.setDescriptor(methodIdentification);dta.resolveAttributeStrings(this.embeddedValueResolver);}if (logger.isTraceEnabled()) {logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);}//在这里将解析出来的 TransactionAttribute添加到缓存中并返回this.attributeCache.put(cacheKey, txAttr);}return txAttr;}
}

上面的事务属性TransactionAttribute不为空,就说明当前类可以被用来生成aop代理,进行事务的增强处理。就会调用

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

来生成对应的代理类,来进行事务处理。

5.生成对应代理类

我们进入createProxy方法去看看代理类的生成过程

//这个方法在AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}//这个是代理类的工程,下面主要是设置一些属性,会在方法的最后一行proxyFactory.getProxy(classLoader);生成代理对象,我们直接进去看看ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// Use original ClassLoader if bean class not locally loaded in overriding class loaderClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}return proxyFactory.getProxy(classLoader);}
	public Object getProxy(@Nullable ClassLoader classLoader) {//先创建对应类的代理类,然后使用代理类生成代理对象return createAopProxy().getProxy(classLoader);}
	protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}//在这会调用实际工厂DefaultAopProxyFactory去生成代理类return getAopProxyFactory().createAopProxy(this);}
	//这个方法在DefaultAopProxyFactorypublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!NativeDetector.inNativeImage() &&(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}//如果是一个接口,或者是一个proxy类,就会都java的动态代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}//其他的就会走到这里//我们当前的是com.springboot.transaction.service.impl.UserServiceImpl就会走到这里//到这里代理类就生成了,后续就会用这个去生成我们需要的代理对象return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
//这个方法在CglibAopProxy,具体生成代理类也会是在这里@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {proxySuperClass = rootClass.getSuperclass();Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...//具体创建代理类就用的是Enhancer,这和Configuration具体是差不多的,里面一些细节就去不进行看了//具体的做法还是在enhancer上设置属性,最终调用asm,动态生成字节码,加载到jvm,生成新的代理class对象,并创建代理类对象Enhancer enhancer = createEnhancer();if (classLoader != null) {//这里设置classLoader,最终把生成的class加载到jvm时需要enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}//这里设置最终生成代理类的父类com.springboot.transaction.service.impl.UserServiceImplenhancer.setSuperclass(proxySuperClass);//这个是设置最终生成代理类要实现的接口,(SpringProxy.class,Advised.class).我们后面会去看看这个方法enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));//这个是设置代理类名称的生成策略enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//这个是设置代理类的生成策略,也就是字节码生成策略,最终的字节码生成会由这个类来完成(调用它的generate方法)enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));//这里是设置代理中要使用的拦截器Callback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call above//这里是设置根据我们目标类不同的方法选择不同的拦截器,根据不同的方法调用accept返回一个对应上面callbacks数组的下标,选择不同的拦截器来处理enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.//最终在这里会生成代理目标类,并创建对象//这里需要注意的是:enhancer有个属性useFactory默认是true,这时最终我们生成的代理类除了实现SpringProxy, Advised这两个接口外也会实现org.springframework.cglib.proxy.Factory这个接口//在使用构造方法创建出来对象后会调用((Factory) proxyInstance).setCallbacks(callbacks)将我们上面创建的拦截器注入到对象上去return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

我们看看AopProxyUtils.completeProxiedInterfaces(this.advised)这个方法,这时AopProxyUtils的静态方法

	public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {//继续进去看看return completeProxiedInterfaces(advised, false);}
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {//这里的advised就是前面创建的ProxyFactory对象,之前没有添加过要代理的接口,specifiedInterfaces返回的是个空数组Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();if (specifiedInterfaces.length == 0) {// No user-specified interfaces: check whether target class is an interface.//targetClass 是com.springboot.transaction.service.impl.UserServiceImplClass<?> targetClass = advised.getTargetClass();if (targetClass != null) {if (targetClass.isInterface()) {advised.setInterfaces(targetClass);}else if (Proxy.isProxyClass(targetClass)) {advised.setInterfaces(targetClass.getInterfaces());}specifiedInterfaces = advised.getProxiedInterfaces();}}//这句是判断advised中的接口是否由SpringProxy的子类或子接口,当前advised不包含接口,所以这个是不包含的,注意这里取反了。这个addSpringProxy 就是falseboolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);//isOpaque()这个属性是用来判断是否应该阻止AOP代理转换为 Advised,默认值为“false”,这意味着任何 AOP 代理都可以转换为 Advised。当前这个也是false//第2个条件是判断当前advised是否有接口是Advised的子类或子接口,当前advised不包含接口,所以这个是不包含的,注意这里取反了,这个addAdvised 就是true   boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);//这个decoratingProxy上层传过来的,就是falseboolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));int nonUserIfcCount = 0;if (addSpringProxy) {nonUserIfcCount++;}if (addAdvised) {nonUserIfcCount++;}if (addDecoratingProxy) {nonUserIfcCount++;}//下面就是根据上面判断的值,设置目标代理类要实现的接口的数组大小,然后添加接口。//我们这里会添加两个接口 SpringProxy.class,Advised.classClass<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);int index = specifiedInterfaces.length;if (addSpringProxy) {proxiedInterfaces[index] = SpringProxy.class;index++;}if (addAdvised) {proxiedInterfaces[index] = Advised.class;index++;}if (addDecoratingProxy) {proxiedInterfaces[index] = DecoratingProxy.class;}return proxiedInterfaces;}

我们在这里看看getCallbacks方法,这个方法在CglibAopProxy中

	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {// Parameters used for optimization choices...boolean exposeProxy = this.advised.isExposeProxy();  //falseboolean isFrozen = this.advised.isFrozen();			 //falseboolean isStatic = this.advised.getTargetSource().isStatic();   //true// Choose an "aop" interceptor (used for AOP calls).//这里会创建一个DynamicAdvisedInterceptor,最终的事务代理其实就是通过这个类来完成的Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.Callback targetInterceptor;if (exposeProxy) {targetInterceptor = (isStatic ?//这里返回的是StaticUnadvisedExposedInterceptor,主要是对静态的,不需要代理增强的方法用它来处理,内部实现也就是直接通过反射调用方法,没有做其他处理           new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));}else {targetInterceptor = (isStatic ?new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = (isStatic ?//这里返回的是StaticDispatcher, 这个比较简单,就是可以快速返回原始的类,我们这里就是com.springboot.transaction.service.impl.UserServiceImpl                               new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());//这里会将所有的拦截器都封装都到callback数组中,最终生成的字节码中就会针对不同的方法分别使用不同的拦截器去处理。Callback[] mainCallbacks = new Callback[] {aopInterceptor,  // for normal advicetargetInterceptor,  // invoke target without considering advice, if optimizednew SerializableNoOp(),  // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;// If the target is a static one and the advice chain is frozen,// then we can make some optimizations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);// TODO: small memory optimization here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {Method method = methods[x];List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(method, x);}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}

6. 最终生成的代理类class反编译

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.springboot.transaction.service.impl;import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;public class UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052 extends UserServiceImpl implements SpringProxy, Advised, Factory {private boolean CGLIB$BOUND;public static Object CGLIB$FACTORY_DATA;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static final Callback[] CGLIB$STATIC_CALLBACKS;private MethodInterceptor CGLIB$CALLBACK_0;private MethodInterceptor CGLIB$CALLBACK_1;private NoOp CGLIB$CALLBACK_2;private Dispatcher CGLIB$CALLBACK_3;private Dispatcher CGLIB$CALLBACK_4;private MethodInterceptor CGLIB$CALLBACK_5;private MethodInterceptor CGLIB$CALLBACK_6;private static Object CGLIB$CALLBACK_FILTER;private static final Method CGLIB$findAll$0$Method;private static final MethodProxy CGLIB$findAll$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$equals$1$Method;private static final MethodProxy CGLIB$equals$1$Proxy;private static final Method CGLIB$toString$2$Method;private static final MethodProxy CGLIB$toString$2$Proxy;private static final Method CGLIB$hashCode$3$Method;private static final MethodProxy CGLIB$hashCode$3$Proxy;private static final Method CGLIB$clone$4$Method;private static final MethodProxy CGLIB$clone$4$Proxy;static void CGLIB$STATICHOOK9() {CGLIB$THREAD_CALLBACKS = new ThreadLocal();CGLIB$emptyArgs = new Object[0];Class var0 = Class.forName("com.springboot.transaction.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052");Class var1;Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());CGLIB$equals$1$Method = var10000[0];CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");CGLIB$toString$2$Method = var10000[1];CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");CGLIB$hashCode$3$Method = var10000[2];CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");CGLIB$clone$4$Method = var10000[3];CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");CGLIB$findAll$0$Method = ReflectUtils.findMethods(new String[]{"findAll", "(Ljava/util/Map;)Ljava/util/List;"}, (var1 = Class.forName("com.springboot.transaction.service.impl.UserServiceImpl")).getDeclaredMethods())[0];CGLIB$findAll$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/util/Map;)Ljava/util/List;", "findAll", "CGLIB$findAll$0");}final List CGLIB$findAll$0(Map var1) {return super.findAll(var1);}public final List findAll(Map var1) {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? (List)var10000.intercept(this, CGLIB$findAll$0$Method, new Object[]{var1}, CGLIB$findAll$0$Proxy) : super.findAll(var1);}final boolean CGLIB$equals$1(Object var1) {return super.equals(var1);}public final boolean equals(Object var1) {MethodInterceptor var10000 = this.CGLIB$CALLBACK_5;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_5;}if (var10000 != null) {Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);return var2 == null ? false : (Boolean)var2;} else {return super.equals(var1);}}final String CGLIB$toString$2() {return super.toString();}public final String toString() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();}final int CGLIB$hashCode$3() {return super.hashCode();}public final int hashCode() {MethodInterceptor var10000 = this.CGLIB$CALLBACK_6;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_6;}if (var10000 != null) {Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);return var1 == null ? 0 : ((Number)var1).intValue();} else {return super.hashCode();}}final Object CGLIB$clone$4() throws CloneNotSupportedException {return super.clone();}protected final Object clone() throws CloneNotSupportedException {MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_0;}return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();}public static MethodProxy CGLIB$findMethodProxy(Signature var0) {String var10000 = var0.toString();switch(var10000.hashCode()) {case -508378822:if (var10000.equals("clone()Ljava/lang/Object;")) {return CGLIB$clone$4$Proxy;}break;case 211025071:if (var10000.equals("findAll(Ljava/util/Map;)Ljava/util/List;")) {return CGLIB$findAll$0$Proxy;}break;case 1826985398:if (var10000.equals("equals(Ljava/lang/Object;)Z")) {return CGLIB$equals$1$Proxy;}break;case 1913648695:if (var10000.equals("toString()Ljava/lang/String;")) {return CGLIB$toString$2$Proxy;}break;case 1984935277:if (var10000.equals("hashCode()I")) {return CGLIB$hashCode$3$Proxy;}}return null;}public final int indexOf(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final int indexOf(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).indexOf(var1);}public final boolean isFrozen() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isFrozen();}public final boolean isInterfaceProxied(Class var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isInterfaceProxied(var1);}public final TargetSource getTargetSource() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getTargetSource();}public final int getAdvisorCount() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getAdvisorCount();}public final boolean isProxyTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isProxyTargetClass();}public final void setTargetSource(TargetSource var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setTargetSource(var1);}public final void setExposeProxy(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setExposeProxy(var1);}public final Advisor[] getAdvisors() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getAdvisors();}public final void addAdvisor(Advisor var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1);}public final void addAdvisor(int var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvisor(var1, var2);}public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).replaceAdvisor(var1, var2);}public final boolean isExposeProxy() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isExposeProxy();}public final boolean isPreFiltered() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).isPreFiltered();}public final void setPreFiltered(boolean var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).setPreFiltered(var1);}public final boolean removeAdvice(Advice var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvice(var1);}public final boolean removeAdvisor(Advisor var1) {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).removeAdvisor(var1);}public final void removeAdvisor(int var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).removeAdvisor(var1);}public final void addAdvice(Advice var1) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1);}public final void addAdvice(int var1, Advice var2) throws AopConfigException {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}((Advised)var10000.loadObject()).addAdvice(var1, var2);}public final Class[] getProxiedInterfaces() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).getProxiedInterfaces();}public final String toProxyConfigString() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((Advised)var10000.loadObject()).toProxyConfigString();}public final Class getTargetClass() {Dispatcher var10000 = this.CGLIB$CALLBACK_4;if (var10000 == null) {CGLIB$BIND_CALLBACKS(this);var10000 = this.CGLIB$CALLBACK_4;}return ((TargetClassAware)var10000.loadObject()).getTargetClass();}public UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052() {CGLIB$BIND_CALLBACKS(this);}public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {CGLIB$THREAD_CALLBACKS.set(var0);}public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {CGLIB$STATIC_CALLBACKS = var0;}private static final void CGLIB$BIND_CALLBACKS(Object var0) {UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052 var1 = (UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052)var0;if (!var1.CGLIB$BOUND) {var1.CGLIB$BOUND = true;Object var10000 = CGLIB$THREAD_CALLBACKS.get();if (var10000 == null) {var10000 = CGLIB$STATIC_CALLBACKS;if (var10000 == null) {return;}}Callback[] var10001 = (Callback[])var10000;var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];}}public Object newInstance(Callback[] var1) {CGLIB$SET_THREAD_CALLBACKS(var1);UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052 var10000 = new UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;}public Object newInstance(Callback var1) {throw new IllegalStateException("More than one callback object required");}public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {CGLIB$SET_THREAD_CALLBACKS(var3);UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052 var10000 = new UserServiceImpl$$EnhancerBySpringCGLIB$$fb4ce052;switch(var1.length) {case 0:var10000.<init>();CGLIB$SET_THREAD_CALLBACKS((Callback[])null);return var10000;default:throw new IllegalArgumentException("Constructor not found");}}public Callback getCallback(int var1) {CGLIB$BIND_CALLBACKS(this);Object var10000;switch(var1) {case 0:var10000 = this.CGLIB$CALLBACK_0;break;case 1:var10000 = this.CGLIB$CALLBACK_1;break;case 2:var10000 = this.CGLIB$CALLBACK_2;break;case 3:var10000 = this.CGLIB$CALLBACK_3;break;case 4:var10000 = this.CGLIB$CALLBACK_4;break;case 5:var10000 = this.CGLIB$CALLBACK_5;break;case 6:var10000 = this.CGLIB$CALLBACK_6;break;default:var10000 = null;}return (Callback)var10000;}public void setCallback(int var1, Callback var2) {switch(var1) {case 0:this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;break;case 1:this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;break;case 2:this.CGLIB$CALLBACK_2 = (NoOp)var2;break;case 3:this.CGLIB$CALLBACK_3 = (Dispatcher)var2;break;case 4:this.CGLIB$CALLBACK_4 = (Dispatcher)var2;break;case 5:this.CGLIB$CALLBACK_5 = (MethodInterceptor)var2;break;case 6:this.CGLIB$CALLBACK_6 = (MethodInterceptor)var2;}}public Callback[] getCallbacks() {CGLIB$BIND_CALLBACKS(this);return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5, this.CGLIB$CALLBACK_6};}public void setCallbacks(Callback[] var1) {this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];this.CGLIB$CALLBACK_2 = (NoOp)var1[2];this.CGLIB$CALLBACK_3 = (Dispatcher)var1[3];this.CGLIB$CALLBACK_4 = (Dispatcher)var1[4];this.CGLIB$CALLBACK_5 = (MethodInterceptor)var1[5];this.CGLIB$CALLBACK_6 = (MethodInterceptor)var1[6];}static {CGLIB$STATICHOOK9();}
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Go语言之运算符

    package mainimport "fmt"func main() {fmt.Println("--------------------------")a : 10b : 20fmt.Println(a b)// fmt.Println(a - b)// fmt.Println(a * b)fmt.Println(5 / 2)fmt.Println(5 % 2)// 和-- 在Go语言中与C语言不同,// 和-- 是单独的语句&…...

    2024/5/2 21:59:43
  2. Git-移除版本控制

    分享一个大牛的人工智能教程。零基础&#xff01;通俗易懂&#xff01;风趣幽默&#xff01;希望你也加入到人工智能的队伍中来&#xff01;请点击http://www.captainbed.net 1、预览要删除的文件 git rm -r -n --cached "xxx" 2、移除版本控制 git rm -r --cach…...

    2024/5/2 21:59:39
  3. 嵌入式系统硬件抽象层(HAL BSP)的设计思想

    嵌入式系统硬件抽象层&#xff08;HAL & BSP&#xff09;的设计思想1 前言1.1 层次化思想1.2 模块化思想1.3 对象化思想2 板级支持包&#xff08;BSP&#xff09;3 嵌入式系统硬件抽象层的原理3.1 硬件抽象层的引入3.2 BSP的特点与功能3.3 BSP的设计与实现嵌入式系统初始化…...

    2024/5/2 21:59:36
  4. Java基础知识理解

    1、编写一个控制台程序&#xff0c;输入一个日期&#xff0c;求下一天的日期。要求如下&#xff1a; &#xff08;1&#xff09;在控制台输入一个日期&#xff08;分别输入年、月、日&#xff09;&#xff0c;判断输入的日期是否有效&#xff0c;如果有效&#xff0c;计算该日…...

    2024/5/8 23:45:19
  5. Nginx配置指令之listen

    listen指令 listen:用来配置监听端口。 语法listen address:port...;<br/>listen port [default_server]...;默认值listen *:80 | *:8000位置server listen的设置比较灵活&#xff0c;我们通过几个例子来把常用的设置方式熟悉下&#xff1a; listen 127.0.0.1:8000; /…...

    2024/5/8 20:14:11
  6. Mybatis框架学习笔记(4)

    本篇Mybatis框架学习笔记;紧跟之前的学习 Mybatis框架学习笔记(3)–> 文章目录1.当出现数据库的列字段与实体类的不一致时;需要手动配置字段映射;2.两张表以上的多表映射;完成查询所有的员工(附带地查到员工对应的部门);注意有一对一的关系;完成查询所有的部门;(还要查到部门…...

    2024/5/8 16:41:22
  7. 上班/读研办公度摸鱼如何快速切屏不留痕迹?Win10切屏快捷键赶紧收藏起来

    上班/读研办公度摸鱼如何快速切屏不留痕迹&#xff1f;Win10切屏快捷键赶紧收藏起来 创建新的桌面窗口&#xff0c;可自由切换且任务栏不会有进程显示 创建新的桌面窗口&#xff1a;CtrlWinD 关闭新建的桌面窗口&#xff1a;CtrlWinF4 切换桌面窗口&#xff1a;CtrlWin→&…...

    2024/5/8 20:54:58
  8. [2021.10.29]<UE4学习日记>UI界面、计时器、计分

    一、计时器Timer、计数器 & 显示&#xff1a; 流程&#xff1a; &#xff08;最后为测试打印&#xff0c;实际可以删去&#xff09; 以上语句挂载在蓝图UI_Timer上。 注&#xff1a;记得将“timer”挂到“0”上&#xff0c;才会显示出来。 2.金币&#xff1a;物体Box Col…...

    2024/5/2 21:59:20
  9. Servlect 56天的学习总结。

    servlect常用对象的总结 对象1 ServletConfig对象。 用途&#xff1a;获取静态数据的 。不能共享给其他servlect 方案一 <servlet-name>Servlet1</servlet-name><servlet-class>com.Servlet.Servlet1</servlet-class><!-- 注意<init-param>写…...

    2024/5/2 21:59:16
  10. 零基础学习WEB前端开发(十五):CSS_id选择器及通配符选择器

    目 录 一、id选择器 1.1 语法 1.2 例子 1.3 与类选择器的区别 二、通配符选择器 2.1 语法 2.2 示例 2.3 注意点 一、id选择器 id选择器可以为标有特定id的HTML元素指定特定的样式。 HTML元素以id属性来设置id选择器&#xff0c;CSS中id选择器以#来定义。 1.1…...

    2024/5/2 21:59:11
  11. 【Ybtoj 递推算法强化】划分数列

    解题思路 设lx[i]表示以i为结尾的最长不下降序列的起点&#xff0c;ly[i]表示以i为结尾的最长不上升序列的起点&#xff0c;然后dp[i]表示到i为止最少要分多少段&#xff0c;每次更新完lx[i]&#xff0c;ly[i]lx[i]&#xff0c;ly[i]lx[i]&#xff0c;ly[i]后更新‘在这里插入…...

    2024/5/2 21:59:08
  12. 【3DSlicer】基于心脏ct影像重建3d模型及导出

    3DSlicer4.11 这里使用软件自带数据 可以调整看得更清晰 点击ADD添加两层&#xff0c;双击改名heart,background 点击paint&#xff0c;选中heart&#xff0c;在ct图像中画出心脏区域 选中background&#xff0c;在ct图像中画出心脏外围 可以按住shift和鼠标滚轮调整画…...

    2024/5/2 21:59:04
  13. 云展网教程 | 如何把云展的杂志下载下来上传到自己的网站(服务空间)?

    将杂志在自己的网页上展示有两种方法: 方法一:使用云展网网站提供的嵌入功能:《云展网教程 | 如何获得书橱的嵌入代码?》 方法二:付费会员可以下载网页版杂志上传到自己的网站服务空间使用。 1、从云展网下载zip格式文件2、解压下载的zip文件,会得到几个文件夹、.swf文件…...

    2024/5/2 21:59:00
  14. node-php-server 游戏服务器框架

    做游戏服务器8年多了&#xff0c;用过lua, 用过C, 用过nodejs ,最近用的是php,有些人会说php不是用在web开发吗&#xff0c;怎么能用在游戏服务器的业务逻辑开发&#xff0c;php 怎么跟客户端通信&#xff0c;肯定有很多人不解。 其实很多时候&#xff0c;技术原理都是都是相通…...

    2024/5/2 21:58:56
  15. openGauss的基本使用

    1、查看数据库中所含的表 SELECT distinct(tablename) FROM pg_tables WHERE SCHEMANAME public; 2、查看数据库的用户 SELECT * FROM pg_user; 3、切换到指定的数据库 \c test上述语句代表从当前数据库切换到test数据库。 4、查看数据库 使用\l元命令查看数据库系统…...

    2024/5/2 21:58:51
  16. Goroutine之sync.pool

    sync.pool前言使用源码GetPut理解sync.poolvictim前言 sync.Pool的核心作用 - 读源码&#xff0c;缓存稍后会频繁使用的对象减轻GC压力sync.Pool的Put与Get - Put的顺序为local private-> local shared&#xff0c;Get的顺序为 local private -> local shared -> rem…...

    2024/5/2 21:58:47
  17. nginx 重启失败

    没图忘记截图了 //第一步 nginx路径 -c ningx配置文件 以配置文件的形式启动nginx //第二部 nginx路径 -s reload 重启...

    2024/5/2 21:58:44
  18. 闭包的形成与作用

    前言 以前在学到闭包的时候&#xff0c;感觉并不能明白其中的原理&#xff0c;对于闭包的形成与作用也是模棱两可。经过后面的学习与积累&#xff0c;也逐渐对闭包有了一点自己的理解。 闭包的形成 1.作用域 谈到闭包&#xff0c;就不得不说到作用域。作用域就是所声明变量的一…...

    2024/5/2 21:58:39
  19. 关于UnityHub更换位置后找不到编辑器以及登录界面白屏的问题

    若之前已经有该版本的unity3d&#xff0c;更换位置后显示找不到&#xff0c;可以找出它所在的位置&#xff0c;然后在UnityHub的安装选项中&#xff0c;点击添加已安装版本&#xff0c;该问题就能解决 若显示未登录&#xff0c;且登录界面白屏&#xff0c;可通过以下三个方法解…...

    2024/5/2 21:58:36
  20. Flink状态管理详解:Keyed State和Operator List State深度解析

    Flink的状态管理机制详解 本文将重点跟大家讲解Flink的状态管理机制&#xff0c;包括状态要解决的问题、Flink几种不同类型的状态、Keyed State和Operator List State的使用方法等。相关代码参见的github&#xff1a;https://github.com/luweizheng/flink-tutorials。图片文字均…...

    2024/5/2 21:58:32

最新文章

  1. VBScript与文件的编码

    首先&#xff0c;VBScript的脚本源文件得是ANSI编码的&#xff0c;如果保存为UTF-8格式的&#xff0c;执行时可能会报错&#xff0c;比如你语法什么的都没有问题&#xff0c;不过代码中包含汉字串&#xff0c;那么可能执行时就会出现“未结束的字符串常量”之类的错误。 VBScri…...

    2024/5/9 6:14:50
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. JVM学习笔记

    文章目录 一、内存模型1. 程序计数器2. 栈3. 本地方法栈4. 堆5. 方法区方法区位置字符串常量池位置 6. 直接内存 二、虚拟机参数设置三、类的生命周期1. 加载2. 连接1&#xff09;验证2&#xff09;准备3&#xff09;解析 3. 初始化4. 卸载 四、类加载器1. 启动类加载器2. 扩展…...

    2024/5/7 6:47:46
  4. STL--vector有哪些应用场景

    vector 在 C 中是一种非常灵活和强大的容器&#xff0c;适用于多种不同的应用场景。以下是一些常见的应用场景&#xff1a; 1 动态数据集合&#xff1a;当你不确定数据集的大小&#xff0c;或者数据集的大小会随时间变化时&#xff0c;vector 是理想的选择。例如&#xff0c;在…...

    2024/5/8 15:27:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/7 9:45:25
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; 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
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在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