亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Home Java JavaInterview questions Java interview question: Do you know what circular dependency is? How does Spring solve circular dependencies?

Java interview question: Do you know what circular dependency is? How does Spring solve circular dependencies?

Jan 08, 2021 am 10:33 AM
java spring circular dependency interview

Java interview question: Do you know what circular dependency is? How does Spring solve circular dependencies?

First of all, let me introduce to you what circular dependency is.

(Learning video sharing: java video tutorial)

The so-called circular dependency is that A depends on B, and B depends on A at the same time. The dependence relationship between the two is formed. A ring, usually caused by incorrect encoding. Spring can only solve the problem of circular dependency of properties, but not the problem of circular dependency of constructors, because there is no solution to this problem.

Next, we first write a Demo to demonstrate how Spring handles the problem of property circular dependencies.

Talk is cheap. Show me the code

Step one: Define a class ComponentA, which has a private property componentB.

package com.tech.ioc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author 君戰(zhàn)
 * **/
@Component
public class ComponentA {

	@Autowired
	private ComponentB componentB;

	public void say(){
		componentB.say();
	}

}

Step 2: Define a class ComponentB, which depends on ComponentA. And define a say method to facilitate printing data.

package com.tech.ioc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * @author 君戰(zhàn)
 * **/
@Component
public class ComponentB {

	@Autowired
	private ComponentA componentA;

	public void say(){
		System.out.println("componentA field " + componentA);
		System.out.println(this.getClass().getName() + " -----> say()");
	}

}

The third step: focus, write a class -SimpleContainer, imitating Spring's underlying processing of circular dependencies. If you understand this code, it will be very simple to look at Spring's logic for handling circular dependencies.

package com.tech.ioc;

import java.beans.Introspector;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 演示Spring中循環(huán)依賴是如何處理的,只是個簡版,真實(shí)的Spring依賴處理遠(yuǎn)比這個復(fù)雜。
 * 但大體思路都相同。另外這個Demo很多情況都未考慮,例如線程安全問題,僅供參考。
 * @author 君戰(zhàn)
 *
 * **/
public class SimpleContainer {

	/***
	 * 用于存放完全初始化好的Bean,Bean處于就緒狀態(tài)
	 * 這個Map定義和Spring中一級緩存命名一致
	 * */
	private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

	/***
	 * 用于存放剛創(chuàng)建出來的Bean,其屬性還沒有處理,因此存放在該緩存中的Bean還不可用。
	 * 這個Map定義和Spring中三級緩存命名一致
	 * */
	private final Map<String, Object> singletonFactories = new HashMap<>(16);


	public static void main(String[] args) {
		SimpleContainer container = new SimpleContainer();
		ComponentA componentA = container.getBean(ComponentA.class);
		componentA.say();
	}

	public <T> T getBean(Class<T> beanClass) {
		String beanName = this.getBeanName(beanClass);
		// 首先根據(jù)beanName從緩存中獲取Bean實(shí)例
		Object bean = this.getSingleton(beanName);
		if (bean == null) {
			// 如果未獲取到Bean實(shí)例,則創(chuàng)建Bean實(shí)例
			return createBean(beanClass, beanName);
		}
		return (T) bean;
	}
	/***
	 * 從一級緩存和二級緩存中根據(jù)beanName來獲取Bean實(shí)例,可能為空
	 * */
	private Object getSingleton(String beanName) {
		// 首先嘗試從一級緩存中獲取
		Object instance = singletonObjects.get(beanName);
		if (instance == null) { // Spring 之所以能解決循環(huán)依賴問題,也是靠著這個三級緩存--singletonFactories
			instance = singletonFactories.get(beanName);
		}
		return instance;
	}

	/***
	 * 創(chuàng)建指定Class的實(shí)例,返回完全狀態(tài)的Bean(屬性可用)
	 *
	 * */
	private <T> T createBean(Class<T> beanClass, String beanName) {
		try {
			Constructor<T> constructor = beanClass.getDeclaredConstructor();
			T instance = constructor.newInstance();
			// 先將剛創(chuàng)建好的實(shí)例存放到三級緩存中,如果沒有這一步,Spring 也無法解決三級緩存
			singletonFactories.put(beanName, instance);
			Field[] fields = beanClass.getDeclaredFields();
			for (Field field : fields) {
				Class<?> fieldType = field.getType();
				field.setAccessible(true); 
				// 精髓是這里又調(diào)用了getBean方法,例如正在處理ComponentA.componentB屬性,
				// 執(zhí)行到這里時就會去實(shí)例化ComponentB。因?yàn)樵趃etBean方法首先去查緩存,
				// 而一級緩存和三級緩存中沒有ComponentB實(shí)例數(shù)據(jù),所以又會調(diào)用到當(dāng)前方法,
				// 而在處理ComponentB.componentA屬性時,又去調(diào)用getBean方法去緩存中查找,
				// 因?yàn)樵谇懊嫖覀儗omponentA實(shí)例放入到了三級緩存,因此可以找到。
				// 所以ComponentB的實(shí)例化結(jié)束,方法出棧,返回到實(shí)例化ComponentA的方法棧中,
				// 這時ComponentB已經(jīng)初始化完成,因此ComponentA.componentB屬性賦值成功!
				field.set(instance, this.getBean(fieldType));
			}
			// 最后再將初始化好的Bean設(shè)置到一級緩存中。
			singletonObjects.put(beanName, instance);
			return instance;
		} catch (Exception e) {
			e.printStackTrace();
		}
		throw new IllegalArgumentException();
	}

	/**
	 * 將類名小寫作為beanName,Spring底層實(shí)現(xiàn)和這個差不多,也是使用javaBeans的
	 * {@linkplain Introspector#decapitalize(String)}
	 **/
	private String getBeanName(Class<?> clazz) {
		String clazzName = clazz.getName();
		int index = clazzName.lastIndexOf(".");
		String className = clazzName.substring(index);
		return Introspector.decapitalize(className);
	}
}

If all the students have read and understood the above code, then we will conduct a real source code analysis of Spring's circular dependency problem. I believe it will be easy to read it again.

Underlying source code analysis

The analysis starts with the doGetBean method of AbstractBeanFactory. You can see that transformedBeanName is first called in this method (actually to deal with the BeanName problem), which has the same effect as the getBeanName method we wrote ourselves, but Spring considers it much more complicated than this because there are FactoryBean and alias issues.

// AbstractBeanFactory#doGetBean
protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// ?。?!重點(diǎn)是這里,首先從緩存中beanName來獲取對應(yīng)的Bean。
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// 執(zhí)行到這里說明緩存中存在指定beanName的Bean實(shí)例,getObjectForBeanInstance是用來處理獲取到的Bean是FactoryBean問題
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		else {
			try {
				// 刪除與本次分析無關(guān)代碼....
				// 如果是單例Bean,則通過調(diào)用createBean方法進(jìn)行創(chuàng)建
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						} catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
				
				}	
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
		return (T) bean;
	}

The getSingleton method has an overloaded method. The overloaded getSingleton method is called here. Note that the boolean parameter value passed here is true, because this value determines whether exposure of early beans is allowed.

// DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}
// DefaultSingletonBeanRegistry#getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 首先從一級緩存中獲取
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 如果一級緩存中未獲取到,再從二級緩存中獲取
			singletonObject = this.earlySingletonObjects.get(beanName);
			// 如果未從二級緩存中獲取到并且allowEarlyReference值為true(前面?zhèn)鞯臑閠rue)
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
				   //Double Check 
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							// 最后嘗試去三級緩存中獲取
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								// 保存到二級緩存
								this.earlySingletonObjects.put(beanName, singletonObject);
								// 從三級緩存中移除
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

(For more interview questions, please visit: java interview questions and answers)

ok, after reading how Spring obtains Bean instances from the cache, then Take a look at how the creatBean method creates the Bean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	// 刪除與本次分析無關(guān)的代碼...
	try {// createBean方法底層是通過調(diào)用doCreateBean來完成Bean創(chuàng)建的。
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean &#39;" + beanName + "&#39;");
		}
		return beanInstance;
	} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		throw ex;
	} catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}
// AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 創(chuàng)建Bean實(shí)例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		// 如果允許當(dāng)前Bean早期曝光。只要Bean是單例的并且allowCircularReferences 屬性為true(默認(rèn)為true)
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			// 這里調(diào)用了addSingletonFactory方法將剛創(chuàng)建好的Bean保存到了三級緩存中。
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// 刪除與本次分析無關(guān)的代碼.....
		Object exposedObject = bean;
		try {// Bean屬性填充
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化Bean,熟知的Aware接口、InitializingBean接口.....都是在這里調(diào)用
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		} catch (Throwable ex) {
			
		}
		// 刪除與本次分析無關(guān)的代碼.....
		return exposedObject;
	}

First analyze the addSingletonFactory method, because the Bean is saved to the third-level cache in this method.

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(singletonFactory, "Singleton factory must not be null");
	synchronized (this.singletonObjects) {
		// 如果一級緩存中不存在指定beanName的key
		if (!this.singletonObjects.containsKey(beanName)) {
			// 將剛創(chuàng)建好的Bean實(shí)例保存到三級緩存中
			this.singletonFactories.put(beanName, singletonFactory);
			// 從二級緩存中移除。
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}
}

The dependency injection of processing beans is completed by the populateBean method, but the entire execution link is too long, so I will not go into it here. I will only talk about how the IoC container calls it step by step when processing dependencies. getBean method, so that it matches the logic we wrote ourselves to handle field injection.

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// 刪除與本次分析無關(guān)代碼...
	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		// 遍歷所有已注冊的BeanPostProcessor接口實(shí)現(xiàn)類,如果實(shí)現(xiàn)類是InstantiationAwareBeanPostProcessor接口類型的,調(diào)用其postProcessProperties方法。
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				// 刪除與本次分析無關(guān)代碼...
				pvs = pvsToUse;
			}
		}
		// 刪除與本次分析無關(guān)代碼...
	}
	
}

In Spring, the @Autowired annotation is processed by the AutowiredAnnotationBeanPostProcessor class, and the @Resource annotation is processed by the CommonAnnotationBeanPostProcessor class. Both classes implement the InstantiationAwareBeanPostProcessor interface and are completed in the overridden postProcessProperties method. Dependency injection. Here we analyze the processing of @Autowired annotation.

// AutowiredAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// 根據(jù)beanName以及bean的class去查找Bean的依賴元數(shù)據(jù)-InjectionMetadata 
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {// 調(diào)用inject方法
			metadata.inject(bean, beanName, pvs);
		} catch (BeanCreationException ex) {
			throw ex;
		} catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

In the inject method of InjectionMetadata, obtain all the dependent elements (InjectedElement) of the current Bean that need to be processed. This is a collection, traverse the collection, and call the inject method of each dependency injection element.

// InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	// 獲取當(dāng)前Bean所有的依賴注入元素(可能是方法,也可能是字段)
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		// 如果當(dāng)前Bean的依賴注入項(xiàng)不為空,遍歷該依賴注入元素
		for (InjectedElement element : elementsToIterate) {
			// 調(diào)用每一個依賴注入元素的inject方法。
			element.inject(target, beanName, pvs);
		}
	}
}

Two internal classes are defined in the AutowiredAnnotationBeanPostProcessor class - AutowiredFieldElement and AutowiredMethodElement are inherited from InjectedElement, which correspond to field injection and method injection respectively.

Java interview question: Do you know what circular dependency is? How does Spring solve circular dependencies?

Take the commonly used field injection as an example. In the inject method of AutowiredFieldElement, first determine whether the current field has been processed. If it has been processed, it will be cached directly. Otherwise, call the BeanFactory's resolveDependency method to handle dependencies.

// AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Field field = (Field) this.member;
		Object value;
		if (this.cached) {// 如果當(dāng)前字段已經(jīng)被處理過,直接從緩存中獲取
			value = resolvedCachedArgument(beanName, this.cachedFieldValue);
		} else {
			// 構(gòu)建依賴描述符
			DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
			desc.setContainingClass(bean.getClass());
			Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
			Assert.state(beanFactory != null, "No BeanFactory available");
			TypeConverter typeConverter = beanFactory.getTypeConverter();
			try {// 調(diào)用BeanFactory的resolveDependency來解析依賴
				value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
			} catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
			}
			// 刪除與本次分析無關(guān)代碼....
		}
		if (value != null) {
			// 通過反射來對屬性進(jìn)行賦值
			ReflectionUtils.makeAccessible(field);
			field.set(bean, value);
		}
	}
}

The resolveDependency method implemented in DefaultListableBeanFactory ultimately calls the doResolveDependency method to complete the dependency resolution function. In the Spring source code, if there is a do method, then this method is the real way to do the work.

// DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		// .....
		// 如果在字段(方法)上添加了@Lazy注解,那么在這里將不會真正的去解析依賴
		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
				descriptor, requestingBeanName);
		if (result == null) {
			// 如果未添加@Lazy注解,那么則調(diào)用doResolveDependency方法來解析依賴
			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
		}
		return result;
}
// DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

	//.....
	try {
		// 根據(jù)名稱以及類型查找合適的依賴
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (matchingBeans.isEmpty()) {// 如果未找到相關(guān)依賴
			if (isRequired(descriptor)) { // 如果該依賴是必須的(例如@Autowired的required屬性),直接拋出異常
				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
			}
			return null;
		}

		String autowiredBeanName;
		Object instanceCandidate;
		// 如果查找到的依賴多于一個,例如某個接口存在多個實(shí)現(xiàn)類,并且多個實(shí)現(xiàn)類都注冊到IoC容器中。
		if (matchingBeans.size() > 1) {// 決定使用哪一個實(shí)現(xiàn)類,@Primary等方式都是在這里完成
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
				} else { 
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		} else {
			// We have exactly one match.
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		// 如果查找到的依賴是某個類的Class(通常如此),而不是實(shí)例,
		//調(diào)用描述符的方法來根據(jù)類型resolveCandidate方法來獲取該類型的實(shí)例。
		if (instanceCandidate instanceof Class) {
			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
		}
		//...
}

In the resolveCandidate method of the dependency descriptor, the acquisition of the dependent Bean instance is completed by calling the getBean method of the BeanFactory.

// DependencyDescriptor#resolveCandidate
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

	return beanFactory.getBean(beanName);
}

In the implementation of the getBean method, it is still completed by calling the doGetBean method. This is basically the same as the dependency processing we wrote ourselves, except that what we wrote ourselves is relatively simple, and Spring has to consider and handle complex scenarios, so the code is more complicated, but the general idea is the same.

// AbstractBeanFactory#getBean
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

The key point is the demo we wrote earlier to handle circular dependencies. If you understand that code and look at Spring's circular dependency processing, you will find that it is very simple.

Summarize:

Circular dependency means that there is a mutual reference relationship between two beans. For example, A depends on B, and B depends on A. However, Spring can only solve the circular dependency of properties, but not the circular dependency of constructors. This scenario cannot be solved.

The key to Spring's solution to circular dependencies is to first store the beans in the third-level cache when processing the attribute dependencies of the beans. When there are circular dependencies, obtain the relevant beans from the third-level cache, and then retrieve them from the third-level cache. Removed from the first-level cache, stored in the second-level cache, and finally stored in the first-level cache after initialization.

Related recommendations: java introductory tutorial

The above is the detailed content of Java interview question: Do you know what circular dependency is? How does Spring solve circular dependencies?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72
VSCode settings.json location VSCode settings.json location Aug 01, 2025 am 06:12 AM

The settings.json file is located in the user-level or workspace-level path and is used to customize VSCode settings. 1. User-level path: Windows is C:\Users\\AppData\Roaming\Code\User\settings.json, macOS is /Users//Library/ApplicationSupport/Code/User/settings.json, Linux is /home//.config/Code/User/settings.json; 2. Workspace-level path: .vscode/settings in the project root directory

Mastering Dependency Injection in Java with Spring and Guice Mastering Dependency Injection in Java with Spring and Guice Aug 01, 2025 am 05:53 AM

DependencyInjection(DI)isadesignpatternwhereobjectsreceivedependenciesexternally,promotingloosecouplingandeasiertestingthroughconstructor,setter,orfieldinjection.2.SpringFrameworkusesannotationslike@Component,@Service,and@AutowiredwithJava-basedconfi

How to handle transactions in Java with JDBC? How to handle transactions in Java with JDBC? Aug 02, 2025 pm 12:29 PM

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

Understanding the Java Virtual Machine (JVM) Internals Understanding the Java Virtual Machine (JVM) Internals Aug 01, 2025 am 06:31 AM

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

How to work with Calendar in Java? How to work with Calendar in Java? Aug 02, 2025 am 02:38 AM

Use classes in the java.time package to replace the old Date and Calendar classes; 2. Get the current date and time through LocalDate, LocalDateTime and LocalTime; 3. Create a specific date and time using the of() method; 4. Use the plus/minus method to immutably increase and decrease the time; 5. Use ZonedDateTime and ZoneId to process the time zone; 6. Format and parse date strings through DateTimeFormatter; 7. Use Instant to be compatible with the old date types when necessary; date processing in modern Java should give priority to using java.timeAPI, which provides clear, immutable and linear

Comparing Java Frameworks: Spring Boot vs Quarkus vs Micronaut Comparing Java Frameworks: Spring Boot vs Quarkus vs Micronaut Aug 04, 2025 pm 12:48 PM

Pre-formanceTartuptimeMoryusage, Quarkusandmicronautleadduetocompile-Timeprocessingandgraalvsupport, Withquarkusoftenperforminglightbetterine ServerLess scenarios.2.Thyvelopecosyste,

Understanding Network Ports and Firewalls Understanding Network Ports and Firewalls Aug 01, 2025 am 06:40 AM

Networkportsandfirewallsworktogethertoenablecommunicationwhileensuringsecurity.1.Networkportsarevirtualendpointsnumbered0–65535,withwell-knownportslike80(HTTP),443(HTTPS),22(SSH),and25(SMTP)identifyingspecificservices.2.PortsoperateoverTCP(reliable,c

How does garbage collection work in Java? How does garbage collection work in Java? Aug 02, 2025 pm 01:55 PM

Java's garbage collection (GC) is a mechanism that automatically manages memory, which reduces the risk of memory leakage by reclaiming unreachable objects. 1.GC judges the accessibility of the object from the root object (such as stack variables, active threads, static fields, etc.), and unreachable objects are marked as garbage. 2. Based on the mark-clearing algorithm, mark all reachable objects and clear unmarked objects. 3. Adopt a generational collection strategy: the new generation (Eden, S0, S1) frequently executes MinorGC; the elderly performs less but takes longer to perform MajorGC; Metaspace stores class metadata. 4. JVM provides a variety of GC devices: SerialGC is suitable for small applications; ParallelGC improves throughput; CMS reduces

See all articles