티스토리 뷰

Programming/Spring

Enhanced Registrar

Albothyl 2019. 4. 12. 15:52

@Enable + Registrar 는 Application 생성 후에 Registarar가 실행되어 Bean을 생성 /등록해서, Application Code에서 @Autowired로 DI할 수 없는 문제점이 있었다. 이 문제를 해결하기 위한 개선된 코드를 추가한다.

 

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.reflect.ClassPath;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class EnhancedPracticeConfigRegistrar implements ImportBeanDefinitionRegistrar {

	private final String basePackageClasses = "basePackageClasses";
	private final String targetAnnotation = "targetAnnotation";

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// get metadata
		final AnnotationAttributes annotationAttributes = new AnnotationAttributes(importingClassMetadata.getAnnotationAttributes(EnhancedEnablePracticeConfigAnnotation.class.getName()));
		Class<?>[] baseClasses = annotationAttributes.getClassArray(basePackageClasses);
		Class<?> targetClasses = annotationAttributes.getClass(targetAnnotation);

		// covert to bean definition
		List<AbstractBeanDefinition> beanDefinitionList = scan(baseClasses, targetClasses).stream()
			.map(this::createBeanDefinition)
			.collect(Collectors.toList());

		for (AbstractBeanDefinition beanDefinition : beanDefinitionList) {
			registBeanDefinition(registry, beanDefinition);
		}
	}

	private List<Class> scan(Class<?>[] basePackageClasses, Class targetClass) {
		List<Class> targetClassList = Lists.newArrayList();

		for (Class<?> basePackageClass : basePackageClasses) {
			ImmutableSet<ClassPath.ClassInfo> basePackageClassInformation = getClassPath(basePackageClass).getTopLevelClassesRecursive(basePackageClass.getPackage().getName());

			for (ClassPath.ClassInfo packageClassInformation : basePackageClassInformation) {
				if (packageClassInformation.load().isAnnotationPresent(targetClass)) {
					targetClassList.add(packageClassInformation.load());
				}
			}
		}

		return targetClassList;
	}

	private AbstractBeanDefinition createBeanDefinition(Class clazz) {
		return BeanDefinitionBuilder
			.genericBeanDefinition(clazz)
			.getBeanDefinition();
	}

	private void registBeanDefinition(BeanDefinitionRegistry registry, AbstractBeanDefinition beanDefinition) {
		String beanName = StringUtils.uncapitalize(beanDefinition.getBeanClass().getSimpleName());
		registry.registerBeanDefinition(beanName, beanDefinition);
	}

	private ClassPath getClassPath(Class basePackageClass) {
		try {
			return ClassPath.from(basePackageClass.getClassLoader());
		} catch (IOException e) {
			throw new IllegalStateException("invalid class path");
		}
	}
}
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ EnhancedPracticeConfigRegistrar.class })
public @interface EnhancedEnablePracticeConfigAnnotation {
	Class<?>[] basePackageClasses();
	Class<?> targetAnnotation();
}
@EnhancedEnablePracticeConfigAnnotation(basePackageClasses = { Practice.class }, targetAnnotation = SpecificAnnotation.class )

'Programming > Spring' 카테고리의 다른 글

SmartLifecycle  (0) 2019.06.10
JDBC Template  (0) 2019.05.05
@Enable + Registrar  (0) 2019.04.11
ControllerAdvice  (1) 2019.04.01
Request Param Validate (JSR-303)  (0) 2019.03.30
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함