Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@752 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
15 changed files with 617 additions and 22 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.beans.factory.annotation; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* Marks a method as being a factory-method of the class. Use during component scanning |
||||
* to create a bean definition that has factory-bean and factory-method metadata |
||||
* |
||||
* @author Mark Pollack |
||||
* @since 3.0 |
||||
* @see RequiredAnnotationBeanPostProcessor |
||||
*/ |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target({ElementType.METHOD}) |
||||
public @interface FactoryMethod { |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2002-2008 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.beans.factory.annotation; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
|
||||
/** |
||||
* Marker annotation identical in functionality with <aop:scoped-proxy/> tag. Provides a smart |
||||
* proxy backed by a scoped bean, which can be injected into object instances (usually singletons) |
||||
* allowing the same reference to be held while delegating method invocations to the backing, scoped |
||||
* beans. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
@Target(ElementType.METHOD) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
public @interface ScopedProxy { |
||||
|
||||
/** |
||||
* Use CGLib-based class proxies (true) or JDK interface-based (false). |
||||
* |
||||
* Default is CGLib (true). |
||||
* @return |
||||
*/ |
||||
boolean proxyTargetClass() default true; |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
package org.springframework.core.type; |
||||
|
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
public interface MethodMetadata { |
||||
|
||||
int getModifiers(); |
||||
|
||||
boolean isStatic(); |
||||
|
||||
String getMethodName(); |
||||
|
||||
//TODO does the method return type have a generic wildcard or generic type parameters?
|
||||
|
||||
// annotation metadata
|
||||
|
||||
Set<String> getAnnotationTypes(); |
||||
|
||||
boolean hasAnnotation(String annotationType); |
||||
|
||||
Map<String, Object> getAnnotationAttributes(String annotationType); |
||||
|
||||
/** |
||||
* Determine whether the underlying class has an annotation that |
||||
* is itself annotated with the meta-annotation of the given type. |
||||
* @param metaAnnotationType the meta-annotation type to look for |
||||
* @return whether a matching meta-annotation is defined |
||||
*/ |
||||
boolean hasMetaAnnotation(String metaAnnotationType); |
||||
|
||||
/** |
||||
* Return the names of all meta-annotation types defined on the |
||||
* given annotation type of the underlying class. |
||||
* @return the meta-annotation type names |
||||
*/ |
||||
Set<String> getMetaAnnotationTypes(String annotationType); |
||||
|
||||
Set<String> getAnnotationTypesWithMetaAnnotation(String qualifierClassName); |
||||
} |
||||
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
package org.springframework.core.type; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.AccessibleObject; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils; |
||||
|
||||
public class StandardMethodMetadata implements MethodMetadata { |
||||
|
||||
private final Method introspectedMethod; |
||||
|
||||
public StandardMethodMetadata(Method method) { |
||||
introspectedMethod = method; |
||||
} |
||||
|
||||
public final Method getIntrospectedMethod() { |
||||
return this.introspectedMethod; |
||||
} |
||||
|
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) { |
||||
Annotation[] anns = getIntrospectedMethod().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
Annotation ann = anns[i]; |
||||
if (ann.annotationType().getName().equals(annotationType)) { |
||||
return AnnotationUtils.getAnnotationAttributes(ann); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public Set<String> getAnnotationTypes() { |
||||
Set<String> types = new HashSet<String>(); |
||||
Annotation[] anns = getIntrospectedMethod().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
types.add(anns[i].annotationType().getName()); |
||||
} |
||||
return types; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
public String getMethodName() { |
||||
return introspectedMethod.getName(); |
||||
} |
||||
|
||||
public int getModifiers() { |
||||
return introspectedMethod.getModifiers(); |
||||
} |
||||
|
||||
public boolean hasAnnotation(String annotationType) { |
||||
Annotation[] anns = getIntrospectedMethod().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
if (anns[i].annotationType().getName().equals(annotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public boolean isStatic() { |
||||
return Modifier.isStatic(getIntrospectedMethod().getModifiers()); |
||||
} |
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) { |
||||
Annotation[] anns = getIntrospectedMethod().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
if (anns[i].annotationType().getName().equals(annotationType)) { |
||||
Set<String> types = new HashSet<String>(); |
||||
Annotation[] metaAnns = anns[i].annotationType().getAnnotations(); |
||||
for (Annotation meta : metaAnns) { |
||||
types.add(meta.annotationType().getName()); |
||||
} |
||||
return types; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
public boolean hasMetaAnnotation(String metaAnnotationType) { |
||||
|
||||
//TODO can refactor into shared (utility) method with StandardAnnotationMetadata
|
||||
Annotation[] anns = getIntrospectedMethod().getAnnotations(); |
||||
for (int i = 0; i < anns.length; i++) { |
||||
Annotation[] metaAnns = anns[i].annotationType().getAnnotations(); |
||||
for (Annotation meta : metaAnns) { |
||||
if (meta.annotationType().getName().equals(metaAnnotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public Set<String> getAnnotationTypesWithMetaAnnotation( |
||||
String qualifierClassName) { |
||||
// TODO Auto-generated method stub
|
||||
return null; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
package org.springframework.core.type.classreading; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.Method; |
||||
import java.util.Collection; |
||||
import java.util.HashSet; |
||||
import java.util.Iterator; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
import org.objectweb.asm.AnnotationVisitor; |
||||
import org.objectweb.asm.MethodAdapter; |
||||
import org.objectweb.asm.Opcodes; |
||||
import org.objectweb.asm.Type; |
||||
import org.objectweb.asm.commons.EmptyVisitor; |
||||
import org.springframework.core.type.MethodMetadata; |
||||
|
||||
public class MethodMetadataReadingVisitor extends MethodAdapter implements MethodMetadata { |
||||
|
||||
private final Map<String, Map<String, Object>> attributesMap = new LinkedHashMap<String, Map<String, Object>>(); |
||||
|
||||
private final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>(); |
||||
|
||||
private ClassLoader classLoader; |
||||
private String name; |
||||
private int access; |
||||
private boolean isStatic; |
||||
|
||||
public MethodMetadataReadingVisitor(ClassLoader classLoader, String name, int access) { |
||||
super(new EmptyVisitor()); |
||||
this.classLoader = classLoader; |
||||
this.name = name; |
||||
this.access = access; |
||||
this.isStatic = ((access & Opcodes.ACC_STATIC) != 0); |
||||
} |
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) { |
||||
return this.attributesMap.get(annotationType); |
||||
} |
||||
|
||||
public Set<String> getAnnotationTypes() { |
||||
return this.attributesMap.keySet(); |
||||
} |
||||
|
||||
public String getMethodName() { |
||||
return name; |
||||
} |
||||
|
||||
public int getModifiers() { |
||||
return access; |
||||
} |
||||
|
||||
public boolean hasAnnotation(String annotationType) { |
||||
return this.attributesMap.containsKey(annotationType); |
||||
} |
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) { |
||||
return this.metaAnnotationMap.get(annotationType); |
||||
} |
||||
|
||||
public boolean hasMetaAnnotation(String metaAnnotationType) { |
||||
Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values(); |
||||
for (Set<String> metaTypes : allMetaTypes) { |
||||
if (metaTypes.contains(metaAnnotationType)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public boolean isStatic() { |
||||
return isStatic; |
||||
} |
||||
|
||||
|
||||
public Set<String> getAnnotationTypesWithMetaAnnotation(String metaAnnotationType) { |
||||
|
||||
///metaAnnotationMap.put(className, metaAnnotationTypeNames);
|
||||
Set<String> annotationTypes = new LinkedHashSet<String>(); |
||||
Set< Map.Entry<String, Set<String>> > metaValues = metaAnnotationMap.entrySet(); |
||||
Iterator<Map.Entry<String, Set<String>> > metaIterator = metaValues.iterator(); |
||||
while (metaIterator.hasNext()) |
||||
{ |
||||
Map.Entry<String, Set<String>> entry = metaIterator.next(); |
||||
String attributeType = entry.getKey(); |
||||
Set<String> metaAttributes = entry.getValue(); |
||||
if (metaAttributes.contains(metaAnnotationType)) |
||||
{ |
||||
annotationTypes.add(attributeType); |
||||
} |
||||
} |
||||
return annotationTypes; |
||||
} |
||||
|
||||
@Override |
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { |
||||
final String className = Type.getType(desc).getClassName(); |
||||
final Map<String, Object> attributes = new LinkedHashMap<String, Object>(); |
||||
return new EmptyVisitor() { |
||||
@Override |
||||
public void visit(String name, Object value) { |
||||
// Explicitly defined annotation attribute value.
|
||||
attributes.put(name, value); |
||||
} |
||||
@Override |
||||
public void visitEnd() { |
||||
try { |
||||
Class annotationClass = classLoader.loadClass(className); |
||||
// Check declared default values of attributes in the annotation type.
|
||||
Method[] annotationAttributes = annotationClass.getMethods(); |
||||
for (int i = 0; i < annotationAttributes.length; i++) { |
||||
Method annotationAttribute = annotationAttributes[i]; |
||||
String attributeName = annotationAttribute.getName(); |
||||
Object defaultValue = annotationAttribute.getDefaultValue(); |
||||
if (defaultValue != null && !attributes.containsKey(attributeName)) { |
||||
attributes.put(attributeName, defaultValue); |
||||
} |
||||
} |
||||
// Register annotations that the annotation type is annotated with.
|
||||
Annotation[] metaAnnotations = annotationClass.getAnnotations(); |
||||
Set<String> metaAnnotationTypeNames = new HashSet<String>(); |
||||
for (Annotation metaAnnotation : metaAnnotations) { |
||||
metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName()); |
||||
} |
||||
metaAnnotationMap.put(className, metaAnnotationTypeNames); |
||||
} |
||||
catch (ClassNotFoundException ex) { |
||||
// Class not found
|
||||
} |
||||
attributesMap.put(className, attributes); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
Loading…
Reference in new issue