BAEL-4290: tracking down cause of Spring's “not eligible for auto-proxying” (#10593)

This commit is contained in:
Maciej Główka 2021-03-30 17:53:35 +02:00 committed by GitHub
parent eb35265244
commit ac33d1d438
9 changed files with 258 additions and 0 deletions

View File

@ -25,6 +25,11 @@
<version>${spring-boot-starter.version}</version> <version>${spring-boot-starter.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,12 @@
package com.baeldung.component.autoproxying;
import lombok.Getter;
import org.springframework.stereotype.Component;
@Getter
@Component
public class DataCache {
@RandomInt(min = 2, max = 10)
private int group;
private String name;
}

View File

@ -0,0 +1,33 @@
package com.baeldung.component.autoproxying;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
public class EligibleForAutoProxyRandomIntProcessor implements BeanPostProcessor {
private final RandomIntGenerator randomIntGenerator;
@Lazy
public EligibleForAutoProxyRandomIntProcessor(RandomIntGenerator randomIntGenerator) {
this.randomIntGenerator = randomIntGenerator;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
RandomInt injectRandomInt = field.getAnnotation(RandomInt.class);
if (injectRandomInt != null) {
int min = injectRandomInt.min();
int max = injectRandomInt.max();
int randomValue = randomIntGenerator.generate(min, max);
field.setAccessible(true);
ReflectionUtils.setField(field, bean, randomValue);
}
}
return bean;
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.component.autoproxying;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
public class NotEligibleForAutoProxyRandomIntProcessor implements BeanPostProcessor {
private final RandomIntGenerator randomIntGenerator;
public NotEligibleForAutoProxyRandomIntProcessor(RandomIntGenerator randomIntGenerator) {
this.randomIntGenerator = randomIntGenerator;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
RandomInt injectRandomInt = field.getAnnotation(RandomInt.class);
if (injectRandomInt != null) {
int min = injectRandomInt.min();
int max = injectRandomInt.max();
int randomValue = randomIntGenerator.generate(min, max);
field.setAccessible(true);
ReflectionUtils.setField(field, bean, randomValue);
}
}
return bean;
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.component.autoproxying;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface RandomInt {
int min();
int max();
}

View File

@ -0,0 +1,21 @@
package com.baeldung.component.autoproxying;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Random;
@Slf4j
@Component
public class RandomIntGenerator {
private final Random random = new Random();
private final DataCache dataCache;
public RandomIntGenerator(DataCache dataCache) {
this.dataCache = dataCache;
}
public int generate(int min, int max) {
return random.nextInt(max - min) + min;
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.component.autoproxying;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {EligibleForAutoProxyRandomIntProcessor.class, DataCache.class, RandomIntGenerator.class})
public class EligibleForAutoProxyingIntegrationTest {
private static MemoryLogAppender memoryAppender;
private EligibleForAutoProxyRandomIntProcessor randomIntProcessor;
@Autowired
private DataCache dataCache;
@BeforeClass
public static void setup() {
memoryAppender = new MemoryLogAppender();
memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
Logger logger = (Logger) LoggerFactory.getLogger("org.springframework.context");
logger.setLevel(Level.INFO);
logger.addAppender(memoryAppender);
memoryAppender.start();
}
@Test
public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldPopulated() {
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " +
"is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)");
assertEquals(0, notEligibleEvents.size());
assertNotEquals(0, dataCache.getGroup());
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.component.autoproxying;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class MemoryLogAppender extends ListAppender<ILoggingEvent> {
public void reset() {
this.list.clear();
}
public boolean contains(String string, Level level) {
return this.list.stream()
.anyMatch(event -> event.getMessage().toString().contains(string)
&& event.getLevel().equals(level));
}
public int countEventsForLogger(String loggerName) {
return (int) this.list.stream()
.filter(event -> event.getLoggerName().contains(loggerName))
.count();
}
public List<ILoggingEvent> search(String string) {
return this.list.stream()
.filter(event -> event.getMessage().toString().contains(string))
.collect(Collectors.toList());
}
public List<ILoggingEvent> search(String string, Level level) {
return this.list.stream()
.filter(event -> event.getMessage().toString().contains(string)
&& event.getLevel().equals(level))
.collect(Collectors.toList());
}
public int getSize() {
return this.list.size();
}
public List<ILoggingEvent> getLoggedEvents() {
return Collections.unmodifiableList(this.list);
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.component.autoproxying;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {NotEligibleForAutoProxyRandomIntProcessor.class, DataCache.class, RandomIntGenerator.class})
public class NotEligibleForAutoProxyingIntegrationTest {
private static MemoryLogAppender memoryAppender;
private NotEligibleForAutoProxyRandomIntProcessor proxyRandomIntProcessor;
@Autowired
private DataCache dataCache;
@BeforeClass
public static void setup() {
memoryAppender = new MemoryLogAppender();
memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
Logger logger = (Logger) LoggerFactory.getLogger("org.springframework.context");
logger.setLevel(Level.INFO);
logger.addAppender(memoryAppender);
memoryAppender.start();
}
@Test
public void givenAutowireInBeanPostProcessor_whenSpringContextInitialize_thenNotEligibleLogShouldShowAndGroupFieldNotPopulated() {
List<ILoggingEvent> notEligibleEvents = memoryAppender.search("Bean 'randomIntGenerator' of type [com.baeldung.autoproxying.RandomIntGenerator] " +
"is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)");
assertEquals(1, notEligibleEvents.size());
assertEquals(0, dataCache.getGroup());
}
}