JAVA元注解@interface详解

169 阅读10分钟

注解 Annotation 别名:元数据, 含义:一种代码级别的说明

  • 一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性.
  • 与类、接口、枚举是在同一个层次。 它可以声明在包、类、字段、方法、[局部变量]方法参数等的前面,用来对这些元素进行说明,注释。

作用分类:

  • ①编写文档:通过代码里标识的元数据生成文档

  • ② 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】

  • ③编译检查:通过代码里标识的元数据让[编译器]能够实现基本的编译检查【Override】

元注解: jdk1.5起开始提供了4个元注解,用来定义自定义注解的注解,它们分别是:

@Target 指定注解使用的目标范围(类、方法、字段等),其参考值见类的定义:java.lang.annotation.ElementType

public enum ElementType {
    /**
    用在类、接口(包括注解类型)、枚举类型上*TYPE*
    Class, interface (including annotation type), or enum declaration */
    TYPE,

    /**
    字段声明(包括枚举常量)
    Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

interface (including annotation type) 示例

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {

   /**
    * The name of the service with optional protocol prefix. Synonym for {@link #name()
    * name}. A name must be specified for all clients, whether or not a url is provided.
    * Can be specified as property key, eg: ${propertyKey}.
    * @return the name of the service with optional protocol prefix
    */
   @AliasFor("name")
   String value() default "";

   /**
    * The service id with optional protocol prefix. Synonym for {@link #value() value}.
    * @deprecated use {@link #name() name} instead
    * @return the service id with optional protocol prefix
    */
   @Deprecated
   String serviceId() default "";

   /**
    * This will be used as the bean name instead of name if present, but will not be used
    * as a service id.
    * @return bean name instead of name if present
    */
   String contextId() default "";

   /**
    * @return The service id with optional protocol prefix. Synonym for {@link #value()
    * value}.
    */
   @AliasFor("value")
   String name() default "";

   /**
    * @return the <code>@Qualifier</code> value for the feign client.
    * @deprecated in favour of {@link #qualifiers()}.
    *
    * If both {@link #qualifier()} and {@link #qualifiers()} are present, we will use the
    * latter, unless the array returned by {@link #qualifiers()} is empty or only
    * contains <code>null</code> or whitespace values, in which case we'll fall back
    * first to {@link #qualifier()} and, if that's also not present, to the default =
    * <code>contextId + "FeignClient"</code>.
    */
   @Deprecated
   String qualifier() default "";

   /**
    * @return the <code>@Qualifiers</code> value for the feign client.
    *
    * If both {@link #qualifier()} and {@link #qualifiers()} are present, we will use the
    * latter, unless the array returned by {@link #qualifiers()} is empty or only
    * contains <code>null</code> or whitespace values, in which case we'll fall back
    * first to {@link #qualifier()} and, if that's also not present, to the default =
    * <code>contextId + "FeignClient"</code>.
    */
   String[] qualifiers() default {};

   /**
    * @return an absolute URL or resolvable hostname (the protocol is optional).
    */
   String url() default "";

   /**
    * @return whether 404s should be decoded instead of throwing FeignExceptions
    */
   boolean decode404() default false;

   /**
    * A custom configuration class for the feign client. Can contain override
    * <code>@Bean</code> definition for the pieces that make up the client, for instance
    * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
    *
    * @see FeignClientsConfiguration for the defaults
    * @return list of configurations for feign client
    */
   Class<?>[] configuration() default {};

   /**
    * Fallback class for the specified Feign client interface. The fallback class must
    * implement the interface annotated by this annotation and be a valid spring bean.
    * @return fallback class for the specified Feign client interface
    */
   Class<?> fallback() default void.class;

   /**
    * Define a fallback factory for the specified Feign client interface. The fallback
    * factory must produce instances of fallback classes that implement the interface
    * annotated by {@link FeignClient}. The fallback factory must be a valid spring bean.
    *
    * @see feign.hystrix.FallbackFactory for details.
    * @see FallbackFactory for details.
    * @return fallback factory for the specified Feign client interface
    */
   Class<?> fallbackFactory() default void.class;

   /**
    * @return path prefix to be used by all method-level mappings. Can be used with or
    * without <code>@RibbonClient</code>.
    */
   String path() default "";

   /**
    * @return whether to mark the feign proxy as a primary bean. Defaults to true.
    */
   boolean primary() default true;

}

@Documented

指定被标注的注解会包含在javadoc中。

@Retention

指定注解的生命周期(源码、class文件、运行时),其参考值见类的定义:java.lang.annotation.RetentionPolicy

public enum RetentionPolicy {
    /**
    由编译器丢弃。
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
    注释将由编译器记录在类文件中
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
    注释将由编译器记录在类文件中,并且由VM在运行时保留,因此可以反射地读取它们
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

@Inherited

指定子类可以继承父类的注解,只能是类上的注解,方法和字段的注解不能继承。即如果父类上的注解是@Inherited修饰的就能被子类继承。

jdk1.8又提供了以下两个元注解

@Native

指定字段是一个常量,其值引用native code。

@Repeatable

注解上可以使用重复注解,即可以在一个地方可以重复使用同一个注解,例如:spring中的包扫描注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

   /**
    * Alias for {@link #basePackages}.
    * <p>Allows for more concise annotation declarations if no other attributes
    * are needed &mdash; for example, {@code @ComponentScan("org.my.pkg")}
    * instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
    */
   @AliasFor("basePackages")
   String[] value() default {};

   /**
    * Base packages to scan for annotated components.
    * <p>{@link #value} is an alias for (and mutually exclusive with) this
    * attribute.
    * <p>Use {@link #basePackageClasses} for a type-safe alternative to
    * String-based package names.
    */
   @AliasFor("value")
   String[] basePackages() default {};

   /**
    * Type-safe alternative to {@link #basePackages} for specifying the packages
    * to scan for annotated components. The package of each class specified will be scanned.
    * <p>Consider creating a special no-op marker class or interface in each package
    * that serves no purpose other than being referenced by this attribute.
    */
   Class<?>[] basePackageClasses() default {};

   /**
    * The {@link BeanNameGenerator} class to be used for naming detected components
    * within the Spring container.
    * <p>The default value of the {@link BeanNameGenerator} interface itself indicates
    * that the scanner used to process this {@code @ComponentScan} annotation should
    * use its inherited bean name generator, e.g. the default
    * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the
    * application context at bootstrap time.
    * @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
    * @see AnnotationBeanNameGenerator
    * @see FullyQualifiedAnnotationBeanNameGenerator
    */
   Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

   /**
    * The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components.
    */
   Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

   /**
    * Indicates whether proxies should be generated for detected components, which may be
    * necessary when using scopes in a proxy-style fashion.
    * <p>The default is defer to the default behavior of the component scanner used to
    * execute the actual scan.
    * <p>Note that setting this attribute overrides any value set for {@link #scopeResolver}.
    * @see ClassPathBeanDefinitionScanner#setScopedProxyMode(ScopedProxyMode)
    */
   ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

   /**
    * Controls the class files eligible for component detection.
    * <p>Consider use of {@link #includeFilters} and {@link #excludeFilters}
    * for a more flexible approach.
    */
   String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

   /**
    * Indicates whether automatic detection of classes annotated with {@code @Component}
    * {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
    */
   boolean useDefaultFilters() default true;

   /**
    * Specifies which types are eligible for component scanning.
    * <p>Further narrows the set of candidate components from everything in {@link #basePackages}
    * to everything in the base packages that matches the given filter or filters.
    * <p>Note that these filters will be applied in addition to the default filters, if specified.
    * Any type under the specified base packages which matches a given filter will be included,
    * even if it does not match the default filters (i.e. is not annotated with {@code @Component}).
    * @see #resourcePattern()
    * @see #useDefaultFilters()
    */
   Filter[] includeFilters() default {};

   /**
    * Specifies which types are not eligible for component scanning.
    * @see #resourcePattern
    */
   Filter[] excludeFilters() default {};

   /**
    * Specify whether scanned beans should be registered for lazy initialization.
    * <p>Default is {@code false}; switch this to {@code true} when desired.
    * @since 4.1
    */
   boolean lazyInit() default false;


   /**
    * Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters
    * include filter} or {@linkplain ComponentScan#excludeFilters exclude filter}.
    */
   @Retention(RetentionPolicy.RUNTIME)
   @Target({})
   @interface Filter {

      /**
       * The type of filter to use.
       * <p>Default is {@link FilterType#ANNOTATION}.
       * @see #classes
       * @see #pattern
       */
      FilterType type() default FilterType.ANNOTATION;

      /**
       * Alias for {@link #classes}.
       * @see #classes
       */
      @AliasFor("classes")
      Class<?>[] value() default {};

      /**
       * The class or classes to use as the filter.
       * <p>The following table explains how the classes will be interpreted
       * based on the configured value of the {@link #type} attribute.
       * <table border="1">
       * <tr><th>{@code FilterType}</th><th>Class Interpreted As</th></tr>
       * <tr><td>{@link FilterType#ANNOTATION ANNOTATION}</td>
       * <td>the annotation itself</td></tr>
       * <tr><td>{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}</td>
       * <td>the type that detected components should be assignable to</td></tr>
       * <tr><td>{@link FilterType#CUSTOM CUSTOM}</td>
       * <td>an implementation of {@link TypeFilter}</td></tr>
       * </table>
       * <p>When multiple classes are specified, <em>OR</em> logic is applied
       * &mdash; for example, "include types annotated with {@code @Foo} OR {@code @Bar}".
       * <p>Custom {@link TypeFilter TypeFilters} may optionally implement any of the
       * following {@link org.springframework.beans.factory.Aware Aware} interfaces, and
       * their respective methods will be called prior to {@link TypeFilter#match match}:
       * <ul>
       * <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
       * <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
       * <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
       * <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
       * </ul>
       * <p>Specifying zero classes is permitted but will have no effect on component
       * scanning.
       * @since 4.2
       * @see #value
       * @see #type
       */
      @AliasFor("value")
      Class<?>[] classes() default {};

      /**
       * The pattern (or patterns) to use for the filter, as an alternative
       * to specifying a Class {@link #value}.
       * <p>If {@link #type} is set to {@link FilterType#ASPECTJ ASPECTJ},
       * this is an AspectJ type pattern expression. If {@link #type} is
       * set to {@link FilterType#REGEX REGEX}, this is a regex pattern
       * for the fully-qualified class names to match.
       * @see #type
       * @see #classes
       */
      String[] pattern() default {};

   }

}

所有元注解定义在java.lang.annotation包下面

image.png

其中Annotation是注解的基本接口,所有的注解都继承这个接口。

示例: Autowired

注解的定义 :

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

注解的实现原理 : AutowiredAnnotationBeanPostProcessor (后置处理器)

@Autowired注解的实现原理是通过AutowiredAnnotationBeanPostProcessor这个后置处理器来实现的注解的实现

类:AutowiredAnnotationBeanPostProcessor,通过它的构造方法,可以看到它不仅支持@Autowired还支持@Value注解。


public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {  
  //省略部分代码
 
    /**
	 * Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
	 * standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
	 * <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
	 * if available.
	 */
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}
}

AutowiredAnnotationBeanPostProcessor,它实现了接口类MergedBeanDefinitionPostProcessor的方法postProcessMergedBeanDefinition,这个方法是合并我们定义类的信息,比如:一个类集成了其它类,这个方法会把父类属性和信息合并到子类中。 包括依赖查找的过程!

代码如下:

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        //查找注解的元信息,传入了bean的名称、类型
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
 
   /**
   *
   *查找注解元信息
   */
    private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
        //先读缓存
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
                    //把查找出来的元信息进行构建
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}
 
//构建注解元信息   
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        //判断是否符合条件注解类型(@AutoWired和@Value)
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}
 
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;
 
		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
            //先处理注解字段
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
                //是不是要找的字段
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
                    //静态字段不支持@Autowired
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});
 
           //再处理注解方法
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    //@Autowired不支持静态方法
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});
 
			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
 
		return InjectionMetadata.forElements(elements, clazz);
	}
 
/**
	 * Class representing injection information about an annotated field.
	 */
	private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
 
		private final boolean required;
 
		private volatile boolean cached = false;
 
		@Nullable
		private volatile Object cachedFieldValue;
 
		public AutowiredFieldElement(Field field, boolean required) {
			super(field, null);
			this.required = required;
		}
 
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}
 
 
	/**
	 * Class representing injection information about an annotated method.
	 */
	private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {
 
		private final boolean required;
 
		private volatile boolean cached = false;
 
		@Nullable
		private volatile Object[] cachedMethodArguments;
 
		public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {
			super(method, pd);
			this.required = required;
		}
 
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			if (checkPropertySkipping(pvs)) {
				return;
			}
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
				// Shortcut for avoiding synchronization...
				arguments = resolveCachedArguments(beanName);
			}
			else {
				int argumentCount = method.getParameterCount();
				arguments = new Object[argumentCount];
				DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
				Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				for (int i = 0; i < arguments.length; i++) {
					MethodParameter methodParam = new MethodParameter(method, i);
					DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
					currDesc.setContainingClass(bean.getClass());
					descriptors[i] = currDesc;
					try {
						Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
						if (arg == null && !this.required) {
							arguments = null;
							break;
						}
						arguments[i] = arg;
					}
					catch (BeansException ex) {
						throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
					}
				}
				synchronized (this) {
					if (!this.cached) {
						if (arguments != null) {
							DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
							registerDependentBeans(beanName, autowiredBeans);
							if (autowiredBeans.size() == argumentCount) {
								Iterator<String> it = autowiredBeans.iterator();
								Class<?>[] paramTypes = method.getParameterTypes();
								for (int i = 0; i < paramTypes.length; i++) {
									String autowiredBeanName = it.next();
									if (beanFactory.containsBean(autowiredBeanName) &&
											beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
										cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
												descriptors[i], autowiredBeanName, paramTypes[i]);
									}
								}
							}
							this.cachedMethodArguments = cachedMethodArguments;
						}
						else {
							this.cachedMethodArguments = null;
						}
						this.cached = true;
					}
				}
			}
			if (arguments != null) {
				try {
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}
 
		@Nullable
		private Object[] resolveCachedArguments(@Nullable String beanName) {
			Object[] cachedMethodArguments = this.cachedMethodArguments;
			if (cachedMethodArguments == null) {
				return null;
			}
			Object[] arguments = new Object[cachedMethodArguments.length];
			for (int i = 0; i < arguments.length; i++) {
				arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);
			}
			return arguments;
		}
	}

注入过程的调用关系

//属性处理过程,元信息查找、解析、注入
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        //元信息查找、解析,在上一步已经分析过了
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
            //进行注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}
 
 
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
                //注入
				element.inject(target, beanName, pvs);
			}
		}
	}
 
       /**
		 * Either this or {@link #getResourceToInject} needs to be overridden.
		 */
		protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
				throws Throwable {
            //字段注入
			if (this.isField) {
				Field field = (Field) this.member;
                //设置字段权限为可以访问权限
				ReflectionUtils.makeAccessible(field);
				field.set(target, getResourceToInject(target, requestingBeanName));
			}
			else {//方法注入
                
				if (checkPropertySkipping(pvs)) {
					return;
				}
				try {
					Method method = (Method) this.member;
                    //设置方法权限为可以访问权限
					ReflectionUtils.makeAccessible(method);
					method.invoke(target, getResourceToInject(target, requestingBeanName));
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

@Autowired注解,先通过postProcessMergedBeanDefinition方法->findAutowiringMetadata方法分析查找元信息,并且经过反射写入类信息,再次通过inject方法进行注入。