Skip to content

Commit

Permalink
Auto Configuring beans without Stereotypes
Browse files Browse the repository at this point in the history
  • Loading branch information
itsaviu committed Jun 9, 2019
1 parent 33ba5f5 commit e38d9dc
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 72 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ HELP.md
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
classes/
META-INF

### STS ###
.apt_generated
Expand Down
34 changes: 12 additions & 22 deletions src/main/java/com/firefly/dp/FactoryProducer.java
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
package com.firefly.dp;

import com.firefly.dp.annotations.FactoryMember;
import com.firefly.dp.helper.FactoryHelper;
import com.firefly.dp.helper.FactoryMemberHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

@Component
public class FactoryProducer {

@Autowired
private FactoryMemberHelper factoryMember;

@Autowired
private FactoryHelper factoryHelper;
private List<Class> factoryMembers;

public <T> T getImplemention(Class<T> clazz, String value) {

if (factoryHelper.isFireFlyEnabled()) {
List<Object> implementedClazz = factoryMember.accumulateByParent(clazz);
for (Object o : implementedClazz) {
Annotation[] annotations = o.getClass().getAnnotations();
Optional<Annotation> first = Stream.of(annotations)
.filter(annotation -> annotation.annotationType().equals(FactoryMember.class))
.findFirst();
if (first.isPresent()) {
FactoryMember annotation = (FactoryMember) first.get();
if (annotation.key().equalsIgnoreCase(value))
return (T) o;
}
List<Object> implementedClazz = new FactoryMemberHelper(this.factoryMembers, clazz).accumulateByParent();
for (Object o : implementedClazz) {
Annotation[] annotations = o.getClass().getAnnotations();
Optional<Annotation> first = Stream.of(annotations)
.filter(annotation -> annotation.annotationType().equals(FactoryMember.class))
.findFirst();
if (first.isPresent()) {
FactoryMember annotation = (FactoryMember) first.get();
if (annotation.key().equalsIgnoreCase(value))
return (T) o;
}
}

throw new RuntimeException("FireFly not enabled");
throw new RuntimeException("FireFly not enabled");
}
}
87 changes: 87 additions & 0 deletions src/main/java/com/firefly/dp/FireFlyRegistrar.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.firefly.dp;

import com.firefly.dp.annotations.FactoryMember;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class FireFlyRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {


private Environment environment;

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
try {
List<Class> classes = returnRegisteredFireFlies(metadata);
registerBean(registry, classes);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

public void registerBean(BeanDefinitionRegistry registry, List<Class> clazz) throws BeansException {

BeanDefinition dynamicBean = BeanDefinitionBuilder
.rootBeanDefinition(FactoryProducer.class)
.addPropertyValue("factoryMembers", clazz)
.getBeanDefinition();
BeanDefinitionHolder holder = new BeanDefinitionHolder(dynamicBean, FactoryProducer.class.getName(), new String[]{"Factory-Producer"});

BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);

}


public List<Class> returnRegisteredFireFlies(AnnotationMetadata metadata) throws ClassNotFoundException {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FactoryMember.class);
scanner.addIncludeFilter(annotationTypeFilter);
String packageName = ClassUtils.getPackageName(metadata.getClassName());
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(packageName);
List<Class> clazzList = new ArrayList<>();

for (BeanDefinition bean : candidateComponents) {
clazzList.add(Class.forName(bean.getBeanClassName()));
}

return clazzList;
}

protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(
AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
}

}
10 changes: 6 additions & 4 deletions src/main/java/com/firefly/dp/annotations/EnableFireFly.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.firefly.dp.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.firefly.dp.FireFlyRegistrar;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FireFlyRegistrar.class)
public @interface EnableFireFly {
}
29 changes: 0 additions & 29 deletions src/main/java/com/firefly/dp/helper/FactoryHelper.java

This file was deleted.

23 changes: 6 additions & 17 deletions src/main/java/com/firefly/dp/helper/FactoryMemberHelper.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
package com.firefly.dp.helper;

import com.firefly.dp.annotations.FactoryMember;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import lombok.AllArgsConstructor;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
@AllArgsConstructor
public class FactoryMemberHelper {

@Autowired
private ApplicationContext context;
private List<Class> fireFlyClazz;

private List<Object> fireFlyClazz;
private Class parentClass;

@PostConstruct
public void initiator() {
this.fireFlyClazz = new ArrayList<>(context.getBeansWithAnnotation(FactoryMember.class).values());
}

public List<Object> accumulateByParent(Class parent) {
public List<Object> accumulateByParent() {
return this.fireFlyClazz.stream()
.filter(clazz -> parent.isAssignableFrom(clazz.getClass()))
.filter(clazz -> parentClass.isAssignableFrom(clazz))
.collect(Collectors.toList());
}
}

0 comments on commit e38d9dc

Please sign in to comment.