[Весна] Принцип Autowired и отличие от аннотации Resource

Java

Автосвязанные аннотации

Autowired, как следует из названия, означает автоматическую инъекцию.Ниже приведен исходный код аннотации Autowired:

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

    /**
     * Declares whether the annotated dependency is required.
     * <p>Defaults to {@code true}.
     */
    boolean required() default true;

}

Как видно из реализации Autowired, Autowired можно использовать в конструкторах классов, полях классов, методах классов и типах аннотаций, но Autowired нельзя использовать в классах.

Что касается аннотации Autowired, необходимо решить следующие проблемы:

1. Autowired действует в разных областях (конструкторы, поля, методы), какова его стратегия сборки, по имени или типу?

2. После добавления аннотаций Autowired в конструкторы, поля и методы, кто будет анализировать аннотации Autowired и завершать сборку

3. Откуда берется собранный bean-компонент, это bean-компонент, определенный в xml-файле Spring?

Начните с javadoc Autowired

Получите следующую информацию из javadoc Autowired

1. AutowiredAnnotationBeanPostProcessor отвечает за сканирование аннотаций Autowired и последующее выполнение автоматического внедрения.

2. Вы можете использовать Autowired для автоподключения приватных полей без необходимости определять геттеры/сеттеры для приватных полей для чтения/записи этого поля.

3. Метод класса, аннотированный с помощью Autowired, может быть любым именем метода, любым параметром, Spring найдет подходящий бин из контейнера для сборки, а автоматическая инъекция сеттера аналогична автоматической инъекции поля.

Анализ аннотаций Autowired

Когда в проекте используется аннотация Autowired, необходимо четко указать Spring, что в конфигурации есть ссылка на функцию автоматического внедрения.В конфигурационном файле Spring есть два метода.

1. Настройте AutowiredAnnotationBeanPostProcessor

2. Используйтеcontext:annotation-config/.context:annotationconfig/будет неявно зарегистрирован в контейнере SpringAutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessorа такжеequiredAnnotationBeanPostProcessorЭти 4 процессора BeanPost.

пример

1. Пример 1:

  • UserDao, от которого зависит UserSerice, использует аннотации Autowired.

  • UserDao не определен в файле конфигурации Spring

    Результат: UserDao равен нулю

2. Пример 2:

  • UserDao, от которого зависит UserSerice, использует аннотацию Autowired

  • UserDao определяется в файле конфигурации Spring

   Результат: UserDao равен нулю

3. Пример 3:

  • UserDao, от которого зависит UserSerice, использует аннотацию Autowired

  • UserDao определяется в файле конфигурации Spring

  • Используется веснойcontext:annotation-config/

** Результат: UserDao инжектится правильно, реализация UserDao настроена в Spring, а интерфейс UserDao в UserService, то есть хотя их типы не совсем совпадают, но потому что они реализованы**

отношения, Spring все еще может завершить автоматическую инъекцию

4. Пример 4:

  • UserDao, от которого зависит UserSerice, использует аннотацию Autowired

  • UserDao определяется в файле конфигурации Spring

  • Настройка AutowiredAnnotationBeanPostProcessor в Spring

Результат: UserDao внедряется корректно, как в примере 3.

5. Пример 5:

  • UserDao, от которого зависит UserSerice, использует аннотацию Autowired

  • UserDao имеет два определения в файле конфигурации Spring (с разными идентификаторами).

  • Используется веснойcontext:annotation-config/

результат:

1. Если имя атрибута UserDao совпадает с идентификатором бина, то по принципу соответствия имени атрибута и имени идентификатора автоматическая сборка

2. Если имя атрибута UserDao, определенное в UserService, отличается от двух идентификаторов в конфигурационном файле Spring, инъекция завершается неудачно, выдается исключение, и приглашение не может быть собрано автоматически.

в заключении:

1. Используйте Autowired для автоматического подключения, которое необходимо использовать в файле конфигурации Spring.context:annotation-config/чтобы сообщить Spring, что требуется автоматическое сканирование (AutowiredAnnotationBeanPostProcessor устарел)

2. Автоматическое сопоставление по типу по умолчанию. Когда несколько компонентов, соответствующих условиям, сопоставляются, они сопоставляются в соответствии с именем свойства и идентификатором компонента. автоматическая сборка не удалась

3. При использовании Autowired вы можете использовать аннотацию Qualifier, чтобы явно указать, что при возникновении конфликта следует использовать bean-компонент, соответствующий этому идентификатору.

4. Автосвязывание аннотаций Функция автосвязывания завершает автоматическое внедрение зависимостей, поэтому в компоненте компонент, от которого он зависит, может быть дополнен автоматическим внедрением без явного внедрения его свойств. Тем не менее, эти зависимые bean-компоненты по-прежнему нельзя опускать, их все равно нужно настроить в Spring, единственное, что опущено, — это код конфигурации инъекции свойств bean-компонента.

Аннотация ресурса

Аннотация Resource эквивалентна аннотации Autowried+Qualifier по функциям и назначению. Аннотация Resource является частью спецификации JSR-250 и определена в пакете javax.annoation JDK. Ниже приводится ее определение:

package javax.annotation;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

/**
 * The Resource annotation marks a resource that is needed
 * by the application.  This annotation may be applied to an
 * application component class, or to fields or methods of the
 * component class.  When the annotation is applied to a
 * field or method, the container will inject an instance
 * of the requested resource into the application component
 * when the component is initialized.  If the annotation is
 * applied to the component class, the annotation declares a
 * resource that the application will look up at runtime. <p>
 *
 * Even though this annotation is not marked Inherited, deployment
 * tools are required to examine all superclasses of any component
 * class to discover all uses of this annotation in all superclasses.
 * All such annotation instances specify resources that are needed
 * by the application component.  Note that this annotation may
 * appear on private fields and methods of superclasses; the container
 * is required to perform injection in these cases as well.
 *
 * @since Common Annotations 1.0
 */
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
    /**
     * The JNDI name of the resource.  For field annotations,
     * the default is the field name.  For method annotations,
     * the default is the JavaBeans property name corresponding
     * to the method.  For class annotations, there is no default
     * and this must be specified.
     */
    String name() default "";

    /**
     * The name of the resource that the reference points to. It can
     * link to any compatible resource using the global JNDI names.
     *
     * @since Common Annotations 1.1
     */

    String lookup() default "";

    /**
     * The Java type of the resource.  For field annotations,
     * the default is the type of the field.  For method annotations,
     * the default is the type of the JavaBeans property.
     * For class annotations, there is no default and this must be
     * specified.
     */
    Class<?> type() default java.lang.Object.class;

    /**
     * The two possible authentication types for a resource.
     */
    enum AuthenticationType {
            CONTAINER,
            APPLICATION
    }

    /**
     * The authentication type to use for this resource.
     * This may be specified for resources representing a
     * connection factory of any supported type, and must
     * not be specified for resources of other types.
     */
    AuthenticationType authenticationType() default AuthenticationType.CONTAINER;

    /**
     * Indicates whether this resource can be shared between
     * this component and other components.
     * This may be specified for resources representing a
     * connection factory of any supported type, and must
     * not be specified for resources of other types.
     */
    boolean shareable() default true;

    /**
     * A product specific name that this resource should be mapped to.
     * The name of this resource, as defined by the <code>name</code>
     * element or defaulted, is a name that is local to the application
     * component using the resource.  (It's a name in the JNDI
     * <code>java:comp/env</code> namespace.)  Many application servers
     * provide a way to map these local names to names of resources
     * known to the application server.  This mapped name is often a
     * <i>global</i> JNDI name, but may be a name of any form. <p>
     *
     * Application servers are not required to support any particular
     * form or type of mapped name, nor the ability to use mapped names.
     * The mapped name is product-dependent and often installation-dependent.
     * No use of a mapped name is portable.
     */
    String mappedName() default "";

    /**
     * Description of this resource.  The description is expected
     * to be in the default language of the system on which the
     * application is deployed.  The description can be presented
     * to the Deployer to help in choosing the correct resource.
     */
    String description() default "";
}

Автозаписанная аннотация, сначала сопоставляется по типу, если тип соответствует более чем одному, затем сопоставляется по имени атрибута и идентификатору компонента (можно заставить соответствовать указанному идентификатору компонента с помощью аннотации квалификатора). Аннотация Ресурс находится в другом порядке и имеет следующие возможные ситуации:

  • Аннотация ресурса указывает атрибут имени и атрибут типа.

Стратегия: Во-первых, выполните стратегию сопоставления по имени: Сопоставьте атрибут имени и идентификатор компонента. Если они совпадают, определите, относится ли найденный компонент к типу, указанному атрибутом типа. Если это тип, указанный типом атрибут, совпадение успешно. если неАтрибут type определяет типЗатем выбросьте исключение, оперативное совпадение не удалось; если свойство имени не совпадает с идентификатором компонента компонента, бросьте подсказку исключения без имени идентификатора фасоли.

  • Аннотация ресурса указывает атрибут имени, но не указывает атрибут типа.

Стратегия: найти компонент, идентификатор которого является атрибутом имени, и найти его, независимо от типа, совпадение выполнено успешно; если идентификатор компонента, указанный атрибутом имени, не может быть найден, сопоставление завершается ошибкой и выдается исключение.

  • Аннотация ресурса указывает атрибут типа, но не указывает атрибут имени.

Стратегия: Во-первых, выполните стратегию сопоставления по имени: Сопоставьте имя атрибута и идентификатор компонента. Если есть совпадение, определите, относится ли найденный компонент к типу, указанному атрибутом типа. Если это тип, указанный атрибут type, совпадение успешное. если нетип, указанный атрибутом type, выбрасывается исключение, свидетельствующее о том, что сопоставление не удалось, во-вторых, осуществляется стратегия сопоставления по типу: если имя атрибута не совпадает с id бина, ищется бин типа type, если найден только один, авто -сборка успешна, а остальные случаи терпят неудачу.

  • Аннотация ресурса не указывает атрибут типа и атрибут имени

Стратегия: во-первых, сопоставьте стратегию по имени атрибута, и внедрение будет успешным; если имя атрибута не совпадает, выполняется стратегия сопоставления типов.Успехом будет только один тип сопоставления, а в других случаях произойдет сбой.