gpt4 book ai didi

java - 确保 Spring 托管 bean 的单个实例

转载 作者:太空宇宙 更新时间:2023-11-04 06:38:27 25 4
gpt4 key购买 nike

我创建了一个 spring 方面来处理重试机制。我还创建了一个重试注释。以下是重试注释的代码以及处理该注释的方面。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Retry {
/**
* List of exceptions for which we need to retry method invocation.
*
* @return Array of classes.
*/
Class<?>[] exceptions();

/**
* Number of retries. Default is 3.
*
* @return Number of retires.
*/
int retries() default 3;

/**
* Back of period in ms. Default is 1000 ms.
*
* @return Back off Period.
*/
int backOffPeriod() default 1000;

}

@Aspect
public class RetryInterceptor implements Ordered {

private static final RetryInterceptor instance = new RetryInterceptor();

private RetryInterceptor() {
}

private static final Log logger = LogFactory.getLog(RetryInterceptor.class);
private int order = 100;

@Around("@annotation(retry)")
public Object performOperation(ProceedingJoinPoint pjp, Retry retry) throws Throwable {
Class<?>[] exceptionClasses = retry.exceptions();
Assert.notEmpty(exceptionClasses, "Exception classes cannot be empty.");
int retries = retry.retries();
if (logger.isInfoEnabled()) {
logger.info("Attempting to call " + pjp.toShortString() + " with potential for " + getExceptionClasses(exceptionClasses)
+ " with maximum " + retries + " retries");
}
int numAttempts = 0;
do {
try {
return pjp.proceed();
} catch (Throwable ex) {
// if the exception is not what we're looking for, pass it through
boolean canThrowException = true;
for (Class<?> exceptionClass : exceptionClasses) {
if (exceptionClass.isAssignableFrom(ex.getClass())) {
canThrowException = false;
break;
}
}
// A non-configured exception was found.
if (canThrowException) {
throw ex;
}
// we caught the configured exception, retry unless we've reached the maximum
if (++numAttempts > retries) {
logger.warn("Caught " + ex.getClass().getCanonicalName() + " and exceeded maximum retries (" + retries
+ "), rethrowing.");
throw ex;
}
if (logger.isInfoEnabled()) {
logger.info("Caught " + ex.getClass().getCanonicalName() + " and will retry, attempts: " + numAttempts);
}
}
sleep(retry.backOffPeriod());
} while (numAttempts <= retries);
// this will never execute - we will have either successfully returned or re-thrown an
// exception
return null;
}

@Override
public int getOrder() {
return order;
}

private String getExceptionClasses(Class<?>[] classes) {
StringBuilder builder = new StringBuilder();
builder.append(classes[0].getCanonicalName());
for (int i = 1; i < classes.length; i++) {
builder.append(", ").append(classes[i].getCanonicalName());
}
return builder.toString();
}

public static RetryInterceptor getInstance() {
return instance;
}

// Better than Thread.sleep().
public void sleep(long backOffPeriod) throws InterruptedException {
Object mutex = new Object();
synchronized (mutex) {
mutex.wait(backOffPeriod);
}
}
}

要启用注释,我需要实例化 RetryInterceptor 类。我想确保对于给定的上下文,该对象只有一个实例。如果由于某种原因创建了多个对象,我的建议会被多次应用。我怎样才能完全确保总是有 1 个实例?

最佳答案

我找到了一种方法来做到这一点:)引用:Going Beyond DI我在我的根上下文中注册了一个 BeanDefinitionRegistryPostProcessor,这将确保我想要的类只有一个 BeanDefinition。

package test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

import com.xx.xx.xx.xx.xx.RetryInterceptor;

public class TestBeanFacotryPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
String[] definitionNames = registry.getBeanDefinitionNames();
for (int i = 0, j = 0; i < definitionNames.length; i++) {
Class<?> clazz;
try {
clazz = Class.forName(registry.getBeanDefinition(definitionNames[i]).getBeanClassName());
if (RetryInterceptor.class == clazz && j++ > 0) {
registry.removeBeanDefinition(definitionNames[i]);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}

关于java - 确保 Spring 托管 bean 的单个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24995895/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com