/** * Detect relationships in annotated {@link Bean @Bean} Factory methods. * * @return Relationships detected from factory methods. */ protected Set<Relationship> detectAnnotatedFactoryMethods() { Set<Relationship> result = new HashSet<>(); /* retrieve all beans declared in the application context */ String[] annotateBeans = applicationContext.getBeanDefinitionNames(); ConfigurableBeanFactory factory = applicationContext.getBeanFactory(); for (String beanName : annotateBeans) { /* ... and get the bean definition of each declared beans */ Optional<MethodMetadata> metadata = getMethodMetadata(factory.getMergedBeanDefinition(beanName)); if (metadata.isPresent()) { Set<Relationship> rel = detectMethodMetadata(metadata.get()); result.addAll(rel); } } return result; }
protected Set<Relationship> detectMethodMetadata(final MethodMetadata metadata) { /* * ... get the metadata of the current definition bean for the * annotation DependencyHint. In this case, we retrieve the annotation * on the annotated method @Bean. The map can be null. */ Map<String, Object> hintData = metadata.getAnnotationAttributes(annotation.getName()); /* * ... get the Hint directly from the class (Target = ElementType.TYPE) */ Optional<T> methodAnnotation = getAnnotation(metadata); Set<Relationship> rel = new HashSet<>(); if (!CollectionUtils.isEmpty(hintData)) { rel.addAll(extractFromAnnotationAttributes(hintData)); } else if (methodAnnotation.isPresent()) { rel.addAll(extractFromAnnotation(methodAnnotation.get())); } return rel; }
private Method getFactoryMethod(ConfigurableListableBeanFactory beanFactory, BeanDefinition definition) throws Exception { if (definition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition) .getFactoryMethodMetadata(); if (factoryMethodMetadata instanceof StandardMethodMetadata) { return ((StandardMethodMetadata) factoryMethodMetadata) .getIntrospectedMethod(); } } BeanDefinition factoryDefinition = beanFactory .getBeanDefinition(definition.getFactoryBeanName()); Class<?> factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), beanFactory.getBeanClassLoader()); return getFactoryMethod(definition, factoryClass); }
private Map<String, List<SoapMethodData>> getAnnotatedMethods(AnnotationMetadata metadata) { String annotationName = SoapMethod.class.getCanonicalName(); Map<String, List<SoapMethodData>> soapMethods = new HashMap<>(); Set<MethodMetadata> proxyInterfaceMethods = metadata.getAnnotatedMethods(annotationName); for (MethodMetadata proxyInterfaceMethod : proxyInterfaceMethods) { String soapMethodName = (String) proxyInterfaceMethod.getAnnotationAttributes(annotationName).get("value"); Class<?>[] autowiredFields = (Class<?>[]) proxyInterfaceMethod.getAnnotationAttributes(annotationName).get("autowired"); Assert.hasText(soapMethodName, "Soap method name cannot be null or empty"); if (soapMethods.containsKey(soapMethodName)) { soapMethods.get(soapMethodName).add(new SoapMethodData( proxyInterfaceMethod.getMethodName(), proxyInterfaceMethod.getReturnTypeName(), autowiredFields)); } else { List<SoapMethodData> methodNames = new ArrayList<>(); methodNames.add(new SoapMethodData(proxyInterfaceMethod.getMethodName(), proxyInterfaceMethod.getReturnTypeName(), autowiredFields)); soapMethods.put(soapMethodName, methodNames); } } return soapMethods; }
private static <T> boolean hasCustomBeanDefinition( ConfigurableListableBeanFactory beanFactory, Class<T> type, Class<?> configClass) { String[] names = beanFactory.getBeanNamesForType(type, true, false); if (names == null || names.length != 1) { return false; } BeanDefinition definition = beanFactory.getBeanDefinition(names[0]); if (definition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition) .getFactoryMethodMetadata(); if (factoryMethodMetadata != null) { String className = factoryMethodMetadata.getDeclaringClassName(); return !configClass.getName().equals(className); } } return true; }
private void addDeducedBeanTypeForBeanMethod(ConditionContext context, AnnotatedTypeMetadata metadata, final List<String> beanTypes, final MethodMetadata methodMetadata) { try { // We should be safe to load at this point since we are in the // REGISTER_BEAN phase Class<?> configClass = ClassUtils.forName( methodMetadata.getDeclaringClassName(), context.getClassLoader()); ReflectionUtils.doWithMethods(configClass, new MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { if (methodMetadata.getMethodName().equals(method.getName())) { beanTypes.add(method.getReturnType().getName()); } } }); } catch (Throwable ex) { throw new BeanTypeDeductionException( methodMetadata.getDeclaringClassName(), methodMetadata.getMethodName(), ex); } }
private Method getFactoryMethod(ConfigurableListableBeanFactory beanFactory, BeanDefinition definition) throws Exception { if (definition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition) .getFactoryMethodMetadata(); if (factoryMethodMetadata instanceof StandardMethodMetadata) { return ((StandardMethodMetadata) factoryMethodMetadata) .getIntrospectedMethod(); } } BeanDefinition factoryDefinition = beanFactory .getBeanDefinition(definition.getFactoryBeanName()); Class<?> factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), beanFactory.getBeanClassLoader()); return ReflectionUtils.findMethod(factoryClass, definition.getFactoryMethodName()); }
@Test public void allBeanMethodsArePublic() throws IOException, ClassNotFoundException { Set<String> nonPublicBeanMethods = new HashSet<String>(); for (AnnotationMetadata configurationClass : findConfigurationClasses()) { Set<MethodMetadata> beanMethods = configurationClass .getAnnotatedMethods(Bean.class.getName()); for (MethodMetadata methodMetadata : beanMethods) { if (!isPublic(methodMetadata)) { nonPublicBeanMethods.add(methodMetadata.getDeclaringClassName() + "." + methodMetadata.getMethodName()); } } } assertEquals("Found non-public @Bean methods: " + nonPublicBeanMethods, 0, nonPublicBeanMethods.size()); }
private boolean checkQualifier(BeanDefinition endpointBeanDefinition, Annotation qualifierAnnotation) { if (endpointBeanDefinition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) endpointBeanDefinition; String qualifierCanonicalName = qualifierAnnotation.annotationType().getCanonicalName(); MethodMetadata factoryMethodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata(); if (factoryMethodMetadata.isAnnotated(qualifierCanonicalName)) { if (qualifierAnnotation instanceof Qualifier) { Object value1 = factoryMethodMetadata.getAnnotationAttributes(qualifierCanonicalName).get("value"); Object value2 = ((Qualifier) qualifierAnnotation).value(); if (value1 == null || value2 == null) { throw new IllegalArgumentException("No value found on Qualifier annotation"); } if (value1.equals(value2)) { return true; } } return true; } } return false; }
static Map<Class<? extends Annotation>,AnnotationAttributes> qualifierAttributesFor(final MethodMetadata metadata) { if (metadata instanceof StandardMethodMetadata) { return qualifierFor(metadata, ((StandardMethodMetadata)metadata).getIntrospectedMethod()); } else { if (logger.isDebugEnabled()) { logger.debug(String .format("Found unsupported method meta data %s for method %s.%s", metadata.getClass(), metadata.getDeclaringClassName(),metadata.getMethodName())); } try { // TODO find better way to load the specified @Bean method (ignore parameter etc.) return qualifierFor(metadata, ReflectionUtils.findMethod(Class.forName(metadata.getDeclaringClassName()), metadata.getMethodName(), null)); } catch (final ClassNotFoundException e) { logger.warn(String .format("Cant scan method meta data %s for method %s.%s", metadata.getClass(), metadata.getDeclaringClassName(),metadata.getMethodName()), e); } } return new HashMap<Class<? extends Annotation>, AnnotationAttributes>(); }
/** * Get the annotation from the class instead of the {@link Bean} method. * * @param metadata * Method metadata. * @return An optional target annotation. */ protected Optional<T> getAnnotation(MethodMetadata metadata) { try { return Optional.ofNullable(Class.forName(metadata.getReturnTypeName()).getDeclaredAnnotation(annotation)); } catch (ClassNotFoundException e) { LOGGER.error("Could not load class : " + metadata.getReturnTypeName(), e); } return Optional.empty(); }
@Test public void detectUnknownClass() { ConsumerHintAnnotationRelationshipDetector detector = new ConsumerHintAnnotationRelationshipDetector(); MethodMetadata metadataMock = Mockito.mock(MethodMetadata.class); Mockito.when(metadataMock.getReturnTypeName()).thenReturn("com.n0pe.ISwearThisClassWontExist"); Optional<ConsumerHint> result = detector.getAnnotation(metadataMock); Assertions.assertThat(result.isPresent()).isFalse(); }
private boolean isVerticleBeanDefinition(String beanName, BeanDefinition beanDefinition) { Class<?> beanClass = getBeanClass(beanName, beanDefinition); if (beanClass != null) { if (Verticle.class.isAssignableFrom(beanClass)) { return true; } if (FactoryBean.class.isAssignableFrom(beanClass) && beanDefinition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata(); if (factoryMethodMetadata != null && factoryMethodMetadata.isAnnotated(VerticleDeployment.class.getName())) { return true; } } } return false; }
private AnnotatedTypeMetadata getMetadataFromBeanDefinition(BeanDefinition beanDefinition) { if (beanDefinition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition abd = (AnnotatedBeanDefinition) beanDefinition; MethodMetadata factoryMethodMetadata = abd.getFactoryMethodMetadata(); if (factoryMethodMetadata != null) { return factoryMethodMetadata; } else { return abd.getMetadata(); } } return null; }
private void addDeducedBeanTypeForBeanMethod(ConditionContext context, MethodMetadata metadata, final List<String> beanTypes) { try { // We should be safe to load at this point since we are in the // REGISTER_BEAN phase Class<?> returnType = ClassUtils.forName(metadata.getReturnTypeName(), context.getClassLoader()); beanTypes.add(returnType.getName()); } catch (Throwable ex) { throw new BeanTypeDeductionException(metadata.getDeclaringClassName(), metadata.getMethodName(), ex); } }
private Method getFactoryMethod(ConfigurableListableBeanFactory beanFactory, BeanDefinition definition) throws Exception { if (definition instanceof AnnotatedBeanDefinition) { MethodMetadata factoryMethodMetadata = ((AnnotatedBeanDefinition) definition).getFactoryMethodMetadata(); if (factoryMethodMetadata instanceof StandardMethodMetadata) { return ((StandardMethodMetadata) factoryMethodMetadata).getIntrospectedMethod(); } } BeanDefinition factoryDefinition = beanFactory.getBeanDefinition(definition.getFactoryBeanName()); Class<?> factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), beanFactory.getBeanClassLoader()); return getFactoryMethod(definition, factoryClass); }
private void addDeducedBeanType(ConditionContext context, AnnotatedTypeMetadata metadata, final List<String> beanTypes) { if (metadata instanceof MethodMetadata && metadata.isAnnotated(Bean.class.getName())) { addDeducedBeanTypeForBeanMethod(context, (MethodMetadata) metadata, beanTypes); } }
private String getName(AnnotatedTypeMetadata metadata) { if (metadata instanceof AnnotationMetadata) { return ((AnnotationMetadata) metadata).getClassName(); } if (metadata instanceof MethodMetadata) { MethodMetadata methodMetadata = (MethodMetadata) metadata; return methodMetadata.getDeclaringClassName() + "." + methodMetadata.getMethodName(); } return metadata.toString(); }
private static String getClassOrMethodName(AnnotatedTypeMetadata metadata) { if (metadata instanceof ClassMetadata) { ClassMetadata classMetadata = (ClassMetadata) metadata; return classMetadata.getClassName(); } MethodMetadata methodMetadata = (MethodMetadata) metadata; return methodMetadata.getDeclaringClassName() + "#" + methodMetadata.getMethodName(); }
@Override public boolean hasAnnotatedMethods(String annotationName) { for (MethodMetadata methodMetadata : this.methodMetadataSet) { if (methodMetadata.isAnnotated(annotationName)) { return true; } } return false; }
@Override public Set<MethodMetadata> getAnnotatedMethods(String annotationName) { Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(4); for (MethodMetadata methodMetadata : this.methodMetadataSet) { if (methodMetadata.isAnnotated(annotationName)) { annotatedMethods.add(methodMetadata); } } return annotatedMethods; }
public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName, String returnTypeName, ClassLoader classLoader, Set<MethodMetadata> methodMetadataSet) { super(SpringAsmInfo.ASM_VERSION); this.methodName = methodName; this.access = access; this.declaringClassName = declaringClassName; this.returnTypeName = returnTypeName; this.classLoader = classLoader; this.methodMetadataSet = methodMetadataSet; }
protected String deduceScopeName(MethodMetadata factoryMethodMetadata) { if (getAnnotationToScopeMappings() == null) { return null; } for (AnnotationToScopeMapping annotationToScopeMapping : getAnnotationToScopeMappings()) { if (factoryMethodMetadata.isAnnotated(annotationToScopeMapping.getAnnotation().getName())) { return annotationToScopeMapping.getScope(); } } return null; }
@Test public void testDeduceScopeName_nulls() { CustomScopeAnnotationConfigurer customScopeAnnotationConfigurer = new CustomScopeAnnotationConfigurer(); customScopeAnnotationConfigurer.setAnnotationToScopeMappings(null); assertThat(customScopeAnnotationConfigurer.deduceScopeName((AnnotationMetadata) null)).isNull(); assertThat(customScopeAnnotationConfigurer.deduceScopeName((MethodMetadata) null)).isNull(); }
private void addDeducedBeanType(ConditionContext context, AnnotatedTypeMetadata metadata, final List<String> beanTypes) { if (metadata instanceof MethodMetadata && metadata.isAnnotated(Bean.class.getName())) { addDeducedBeanTypeForBeanMethod(context, metadata, beanTypes, (MethodMetadata) metadata); } }
@Test public void allBeanMethodsArePublic() throws IOException, ClassNotFoundException { Set<String> nonPublicBeanMethods = new HashSet<String>(); for (AnnotationMetadata configurationClass : findConfigurationClasses()) { Set<MethodMetadata> beanMethods = configurationClass .getAnnotatedMethods(Bean.class.getName()); for (MethodMetadata methodMetadata : beanMethods) { if (!isPublic(methodMetadata)) { nonPublicBeanMethods.add(methodMetadata.getDeclaringClassName() + "." + methodMetadata.getMethodName()); } } } assertThat(nonPublicBeanMethods).as("Found non-public @Bean methods").isEmpty(); }
/** * Register default methods on interfaces implemented by the configuration class. */ private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { for (SourceClass ifc : sourceClass.getInterfaces()) { Set<MethodMetadata> beanMethods = ifc.getMetadata().getAnnotatedMethods(Bean.class.getName()); for (MethodMetadata methodMetadata : beanMethods) { if (!methodMetadata.isAbstract()) { // A default method or other concrete method on a Java 8+ interface... configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } } processInterfaces(configClass, ifc); } }