I wrote a simple BeanPostProcessor
to get more familiar with how Spring works
package org.example.demos.beanPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
var context = new AnnotationConfigApplicationContext(Config.class);
Sage sage = context.getBean("sage", Sage.class);
sage.sayWisdom();
}
}
package org.example.demos.beanPostProcessor;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class Config {
}
package org.example.demos.beanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class Sage {
@Wisdom
private String wisdom; // "never assigned"
public void sayWisdom() {
String processedWisdom = process(wisdom);
System.out.println(processedWisdom);
}
private String process(String wisdom) {
String intro = getIntro();
String wiserWisdom = makeItSoundWiser(wisdom);
return intro + " " + wiserWisdom;
}
private String getIntro() {
return "Sage says:";
}
private String makeItSoundWiser(String wisdom) {
return wisdom.replaceAll("\\.(?=\\s|$)|(?<!\\.)(?=$)", "...");
}
}
package org.example.demos.beanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class SimpleWisdomProvider implements WisdomProvider {
private final String[] wisdoms = {
"Tomorrow is often the busiest day of the week.",
"I have always wanted to be somebody, but I see now I should have been more specific.",
"Knowledge is like underwear. It is useful to have it, but not necessary to show it off.",
"Go to Heaven for the climate, Hell for the company.",
"Going to church doesn’t make you a Christian any more than going to a garage makes you an automobile."
};
@Override
public String getWisdom() {
int randomIndex = ThreadLocalRandom.current().nextInt(wisdoms.length);
return wisdoms[randomIndex];
}
}
package org.example.demos.beanPostProcessor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Wisdom {
}
package org.example.demos.beanPostProcessor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.Objects;
@Component
@RequiredArgsConstructor
public class WisdomBeanPostProcessor implements BeanPostProcessor {
private final WisdomProvider wisdomProvider;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
Wisdom wisdom = field.getAnnotation(Wisdom.class);
if (Objects.nonNull(wisdom)) {
field.setAccessible(true);
ReflectionUtils.setField(field, bean, wisdomProvider.getWisdom());
break;
}
}
return bean;
}
}
package org.example.demos.beanPostProcessor;
public interface WisdomProvider {
String getWisdom();
}
It works, but I wonder whether I can make IntelliJ aware of my initialization mechanism so that I don't get a warning
Private field 'wisdom' is never assigned
Slapping @SuppressWarnings
onto my wisdom
field is ugly. I tried hiding it within the @Wisdom
annotation, but it's apparently not really transitive so the warning is still present. Of course, I don't want to disable the warning altogether
What are my options?
Type Alt+Enter on the warning and select Assume field annotated by @Wisdom as implicitly written
in the intention list that appears. Now any field annotated by @Wisdom
will no longer be reported as not assigned.
This will add the annotation to the "Unused declaration" inspection's settings. You can remove it again, by going the settings of this inspection, selecting the Entry Points tab, and clicking the Annotations button. The annotation name will be in the bottom list of the dialog that appears.