如果一个对象只通过接口来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行切换。但是这样会存在一个问题,在传统的依赖注入配置中,我们必须要明确要给属性装配哪一个bean的引用,一旦bean很多,就不好维护了。基于这样的场景,spring使用注解来进行自动装配,解决这个问题。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由spring来完成。与自动装配配合的还有“自动检测”,这 个动作会自动识别哪些类需要被配置成bean,进而来进行装配。这样我们就明白了,自动装配是为了将依赖注入“自动化”的一个简化配置的操作。
装配分为三种:byName, byType, constructor。
public interface AutowireCapableBeanFactory extends BeanFactory {
int AUTOWIRE_NO = 0;
int AUTOWIRE_BY_NAME = 1;
int AUTOWIRE_BY_TYPE = 2;
int AUTOWIRE_CONSTRUCTOR = 3;
}
@Autowired注解是byType类型的,这个注解可以用在属性上面,setter方面上面以及构造器上面。使用这个注解时,就不需要在类中为属性添加setter方法了。但是这个属性是强制性的,也就是说必须得装配上,如果没有找到合适的bean能够装配上,就会抛出异常。这时可以使用required=false来允许可以不被装配上,默认值为true。当required=true时,@Autowired要求必须装配,但是在没有bean能装配上时,就会抛出异常:NoSuchBeanDefinitionException,如果required=false时,则不会抛出异常。
一种情况是同时有多个bean是一个类型的,也会抛出这个异常。此时需要进一步明确要装配哪一个Bean,这时可以组合使用
@Qualifier注解使用byName进行装配,这样可以在多个类型一样的bean中,明确使用哪一个名字的bean来进行装配。@Qualifier注解起到了缩小自动装配候选bean的范围的作用。
@Autowired与@Qualifier是spring提供的 ,@Inject与@Named是java ee的。
@Component
@Slf4j
@AllArgsConstructor
class NoNeedInspectValidator {
private final MaterialProxy materialProxy;
private final ResultVOBuilder resultVOBuilder;
}
/**
* Generates getters for all fields, a useful toString method, and hashCode and equals implementations that check
* all non-transient fields. Will also generate setters for all non-final fields, as well as a constructor.
*
* Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
*
* Complete documentation is found at the project lombok features page for @Data.
*
* @see Getter
* @see Setter
* @see RequiredArgsConstructor
* @see ToString
* @see EqualsAndHashCode
* @see lombok.Value
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
/**
* If you specify a static constructor name, then the generated constructor will be private, and
* instead a static factory method is created that other classes can use to create instances.
* We suggest the name: "of", like so:
*
*
* public @Data(staticConstructor = "of") class Point { final int x, y; }
*
*
* Default: No static constructor, instead the normal constructor is public.
*
* @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
根据源码可以看到 注解@Data含有@RequiredArgsConstructor
/**
* Generates a constructor with required arguments.
* Required arguments are final fields and fields with constraints such as {@code @NonNull}.
*
* Complete documentation is found at the project lombok features page for @Constructor.
*
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
*
* @see NoArgsConstructor
* @see AllArgsConstructor
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface RequiredArgsConstructor {
/**
* If set, the generated constructor will be private, and an additional static 'constructor'
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
*
* @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
* Any annotations listed here are put on the generated constructor.
* The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).
* up to JDK7:
* {@code @RequiredArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}
* from JDK8:
* {@code @RequiredArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
*
* @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
*
* @return The constructor will be generated with this access modifier.
*/
AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
* Placeholder annotation to enable the placement of annotations on the generated code.
* @deprecated Don't use this annotation, ever - Read the documentation.
*/
@Deprecated
@Retention(RetentionPolicy.SOURCE)
@Target({})
@interface AnyAnnotation {}
}
根据源码可以看到 Required arguments are final fields and fields with constraints such as {@code @NonNull}.
会生成一个包含常量,和标识了NotNull的变量的构造方法。生成的构造方法是私有的private
会生成一个包含所有变量的构造方法
区别:执行顺序
Constructor >> @Autowired