美文网首页Spring boot
SpringBoot @Autowired解析

SpringBoot @Autowired解析

作者: 三也视界 | 来源:发表于2020-11-17 09:15 被阅读0次

    Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired的使用来消除 set ,get方法。

    从所属范围来看,Autowired 属于spring的容器配置的一个注解,与它同属容器配置的注解还有:@Required,@Primary, @Qualifier等等。因此@Autowired注解是一个用于容器(container)配置的注解。其次从字面意思来看,@autowired注解来源于英文单词autowire是自动装配的意思,指的一些工业上的用机器代替人口,自动将一些需要完成的组装任务,或者别的一些任务完成。而在spring中,自动装配指的就是使用将Spring容器中的bean自动的和我们需要这个bean的类组装在一起。

    bean实例化和@Autowired装配过程:

    1、一切都是从bean工厂的getBean方法开始的,一旦该方法调用总会返回一个bean实例,无论当前是否存在,不存在就实例化一个并装配,否则直接返回。(Spring MVC是在什么时候开始执行bean的实例化过程的呢?其实就在组件扫描完成之后)
    2、实例化和装配过程中会多次递归调用getBean方法来解决类之间的依赖。
    3、Spring几乎考虑了所有可能性,所以方法特别复杂但完整有条理。
    4、@Autowired最终是根据类型来查找和装配元素的,但是我们设置了<beans default-autowire="byName"/>后会影响最终的类型匹配查找。因为在前面有根据BeanDefinition的autowire类型设置PropertyValue值得一步,其中会有新实例的创建和注册。就是那个autowireByName方法。

    Autowired注解

    autowired有4种模式,byName、byType、constructor、autodectect


    image.png

    @Autowired在何处使用

    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    CONSTRUCTOR:构造
    METHOD:方法
    PARAMETER:参数
    FIELD:字段
    ANNOTATION_TYPE:注解
    

    将@Autowired注解应用于构造函数,如以下示例所示

    public class MovieRecommender {
        private final CustomerPreferenceDao customerPreferenceDao;
        @Autowired
        public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
            this.customerPreferenceDao = customerPreferenceDao;
        }
        // ...
    }
    

    将@Autowired注释应用于setter方法

    public class SimpleMovieLister {
     
        private MovieFinder movieFinder;
     
        @Autowired
        public void setMovieFinder(MovieFinder movieFinder) {
            this.movieFinder = movieFinder;
        }
     
        // ...
    }
    

    将@Autowired注释应用于具有任意名称和多个参数的方法\

    public class MovieRecommender {
     
        private MovieCatalog movieCatalog;
     
        private CustomerPreferenceDao customerPreferenceDao;
     
        @Autowired
        public void prepare(MovieCatalog movieCatalog,
                CustomerPreferenceDao customerPreferenceDao) {
            this.movieCatalog = movieCatalog;
            this.customerPreferenceDao = customerPreferenceDao;
        }
     
        // ...
    }
    

    您也可以将@Autowired应用于字段,或者将其与构造函数混合,如以下示例所示

    public class MovieRecommender {
     
        private final CustomerPreferenceDao customerPreferenceDao;
     
        @Autowired
        private MovieCatalog movieCatalog;
     
        @Autowired
        public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
            this.customerPreferenceDao = customerPreferenceDao;
        }
     
        // ...
    }
    

    直接应用于字段是我们使用的最多的一种方式,但是使用构造方法注入从代码层面却是更加好的

    除此之外,还有以下不太常见的几种方式

    将@Autowired注释添加到需要该类型数组的字段或方法,则spring会从ApplicationContext中搜寻符合指定类型的所有bean,如以下示例所示:

    public class MovieRecommender {
     
        @Autowired
        private MovieCatalog[] movieCatalogs;
     
        // ...
    }
    

    数组可以,我们可以马上举一反三,那容器也可以吗,答案是肯定的,下面是set以及map的例子:

    public class MovieRecommender {
     
        private Set<MovieCatalog> movieCatalogs;
     
        @Autowired
        public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
            this.movieCatalogs = movieCatalogs;
        }
     
        // ...
    }
    
    public class MovieRecommender {
     
        private Map<String, MovieCatalog> movieCatalogs;
     
        @Autowired
        public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
            this.movieCatalogs = movieCatalogs;
        }
     
        // ...
    }
    

    @Autowired参数

    Autowired注解,只有一个required元素,默认是true,也是就是说这个值能改为false。true和false的意义不同。
    require=ture 时,表示解析被标记的字段或方法,一定有对应的bean存在。
    require=false 时,表示解析被标记的字段或方法,没有对应的bean存在不会报错。

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

    不使用xml,而使用注解@Autowire注入一个bean?spring是如何实现的?

    首先,要回答这个问题必须弄明白java是如何解析注解的。

    java是如何解析注解

    我们知道Java和Spring都允许我们创建自定义的注解,在创建注解之后,我们是如何使用的呢?
    SpringBoot自定义注解的简单实现

    以Autowired为例,可以发现,事实上每一个注解本质上都是一个接口,当我们在某一个类当中用到这个注解的时候,就可以通过反射知道是哪个类用了这个注解。也就能拿到这个类的类名,然后就可以根据类名使用反射机制创建对象。与xml的方式就是一样了。大致步骤如下:

    一般过程为下

    1、利用反射机制获取一个类的Class对象
    2、通过这个class对象可以去获取他的每一个方法method,或字段Field等等
    3、Method,Field等类提供了类似于getAnnotation的方法来获取这个一个字段的所有注解
    4、拿到注解之后,我们可以判断这个注解是否是我们要实现的注解,如果是则实现注解逻辑
    现在我们来实现一下这个逻辑,代码如下:

       private static void annotationLogic() {
     
            Class useAnnotationClass = UseAnnotation.class;
            for(Method method : useAnnotationClass.getMethods()) {
                SimpleAnnotation simpleAnnotation = (SimpleAnnotation)method.getAnnotation(SimpleAnnotation.class);
                if(simpleAnnotation != null) {
                    System.out.println(" Method Name : " + method.getName());
                    System.out.println(" value : " + simpleAnnotation.value());
                    System.out.println(" --------------------------- ");
                }
            }
        }
    

    在这里我们实现的逻辑就是打印几句话。从上面的实现逻辑我们不能发现,借助于java的反射我们可以直接拿到一个类里所有的方法,然后再拿到方法上的注解,当然,我们也可以拿到字段上的注解。借助于反射我们可以拿到几乎任何属于一个类的东西。

    @Autowired的原理

    @Autowired注解实现逻辑分析

    知道了上面的知识,我们不难想到,上面的注解虽然简单,但是@Autowired和他最大的区别应该仅仅在于注解的实现逻辑,其他利用反射获取注解等等步骤应该都是一致的。先来看一下@Autowired这个注解在spring的源代码里的定义是怎样的,如下所示:

    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;
     
    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
        boolean required() default true;
    }
    

    阅读代码我们可以看到,Autowired注解可以应用在构造方法,普通方法,参数,字段,以及注解这五种类型的地方,它的保留策略是在运行时。下面,我们不多说直接来看spring对这个注解进行的逻辑实现.

    在Spring源代码当中,Autowired注解位于包org.springframework.beans.factory.annotation之中,该包的内容如下:

    image.png

    首先要知道执行AbstractApplicationContext#refresh()方法时会执行obtainFreshBeanFactory()方法,而这个方法执行时,会在
    DefaultListableBeanFactory#beanDefinitionNames数组中添加internalAutowiredAnnotationProcessor。而internalAutowiredAnnotationProcessor是和AutowiredAnnotationBeanPostProcessor被一起注册到registerPostProcessor中

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    
    
        protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
            PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
        }
    
    

    此方法使用委派模式进行委派。

        public static void registerBeanPostProcessors(
                ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    
            String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
             ...
            registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
             ...
        }
    
    

    getBeanNamesForType 是对前面加载的internalAutowiredAnnotationProcessor进行转换成AutowiredAnnotationBeanPostProcessor然后把返回值postProcessorNames转为priorityOrderedPostProcessors然后注册到registerBeanPostProcessors中

        private static void registerBeanPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    
            for (BeanPostProcessor postProcessor : postProcessors) {
                beanFactory.addBeanPostProcessor(postProcessor);
            }
        }
    
    

    AbstractBeanFactory#beanPostProcessors

        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
            Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
            // Remove from old position, if any
            this.beanPostProcessors.remove(beanPostProcessor);
            // Track whether it is instantiation/destruction aware
            if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
                this.hasInstantiationAwareBeanPostProcessors = true;
            }
            if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
                this.hasDestructionAwareBeanPostProcessors = true;
            }
            // Add to end of list
            this.beanPostProcessors.add(beanPostProcessor);
        }
    
    

    到此知道了AutowiredAnnotationBeanPostProcessor的来龙去脉。下面就开下AutowiredAnnotationBeanPostProcessor如何去解析@Autowired。

    AutowiredAnnotationBeanPostProcessor解析@Autowired

    refresh()执行完registerBeanPostProcessors 方法后,继续执行finishBeanFactoryInitialization(beanFactory);

        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            ...
            // Instantiate all remaining (non-lazy-init) singletons.
            beanFactory.preInstantiateSingletons();
        }
    
    

    这里spring会创建所需要的bean,一般在controller层中引入的service也会在此时依赖加载和创建。

        public void preInstantiateSingletons() throws BeansException {
            if (logger.isTraceEnabled()) {
                logger.trace("Pre-instantiating singletons in " + this);
            }
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                           ...
                getBean(beanName);
                          ...
            }
        ...
    
    

    当执行到我们自定义的controller层时,会在getBean中进行执行autowire解析。

        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
    
        protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
                  return createBean(beanName, mbd, args);
    }
    
    
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                throws BeanCreationException {
          ...
          doCreateBean(beanName, mbdToUse, args);
          ...
    }
    
    

    而doCreateBean是真正的创建bean实现,在创建的时候调用了applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
                throws BeanCreationException {
                  ...
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                ...
        }
    
    

    终于在applyMergedBeanDefinitionPostProcessors中看到了我们熟悉的身影BeanPostProcessor

        protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof MergedBeanDefinitionPostProcessor) {
                    MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                    bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
                }
            }
        }
    
    

    getBeanPostProcessors方法获取的就是上文中添加的AutowiredAnnotationBeanPostProcessor的集合beanPostProcessors
    则执行我们的想看到的AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    
    

    findAutowiringMetadata查询这个beanName中,是否有

        private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
             ...
            metadata = buildAutowiringMetadata(clazz);
             ...
        }
    
    

    经过分析,不难发现Spring对autowire注解的实现逻辑位于类:AutowiredAnnotationBeanPostProcessor之中,已在上图标红。其中的核心处理代码如下:

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
            LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
            Class<?> targetClass = clazz;//需要处理的目标类
           
            do {
                final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
     
                /*通过反射获取该类所有的字段,并遍历每一个字段,并通过方法findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回auotowired相关属性*/  
     
                ReflectionUtils.doWithLocalFields(targetClass, field -> {
                    AnnotationAttributes ann = findAutowiredAnnotation(field);
                    if (ann != null) {//校验autowired注解是否用在了static方法上
                        if (Modifier.isStatic(field.getModifiers())) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("Autowired annotation is not supported on static fields: " + field);
                            }
                            return;
                        }//判断是否指定了required
                        boolean required = determineRequiredStatus(ann);
                        currElements.add(new AutowiredFieldElement(field, required));
                    }
                });
                //和上面一样的逻辑,但是是通过反射处理类的method
                ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                    Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                    if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                        return;
                    }
                    AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
                    if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("Autowired annotation is not supported on static methods: " + method);
                            }
                            return;
                        }
                        if (method.getParameterCount() == 0) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("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));
                    }
                });
        //用@Autowired修饰的注解可能不止一个,因此都加在currElements这个容器里面,一起处理       
                elements.addAll(0, currElements);
                targetClass = targetClass.getSuperclass();
            }
            while (targetClass != null && targetClass != Object.class);
     
            return new InjectionMetadata(clazz, elements);
        }
    

    findAutowiredAnnotation(bridgedMethod)找到这个类的autowire注解的类,添加到InjectionMetadata对象中。然后在checkConfigMembers方法中又注册到beanDefinition中。

        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    
    
        public void checkConfigMembers(RootBeanDefinition beanDefinition) {
            Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
            for (InjectedElement element : this.injectedElements) {
                Member member = element.getMember();
                if (!beanDefinition.isExternallyManagedConfigMember(member)) {
                    beanDefinition.registerExternallyManagedConfigMember(member);
                    checkedElements.add(element);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
                    }
                }
            }
            this.checkedElements = checkedElements;
        }
    

    最后这个方法返回的就是包含所有带有autowire注解修饰的一个InjectionMetadata集合。这个类由两部分组成:

    public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
            this.targetClass = targetClass;
            this.injectedElements = elements;
        }
    

    一是我们处理的目标类,二就是上述方法获取到的所以elements集合。

    有了目标类,与所有需要注入的元素集合之后,我们就可以实现autowired的依赖注入逻辑了,实现的方法如下:

    @Override
        public PropertyValues postProcessPropertyValues(
                PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
     
            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;
        }
    

    它调用的方法是InjectionMetadata中定义的inject方法,如下

    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);
                }
            }
        }
    

    其逻辑就是遍历,然后调用inject方法,inject方法其实现逻辑如下:

            /**
             * 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();
                    }
                }
            }
    

    在这里的代码当中我们也可以看到,是inject也使用了反射技术并且依然是分成字段和方法去处理的。在代码里面也调用了makeAccessible这样的可以称之为暴力破解的方法,但是反射技术本就是为框架等用途设计的,这也无可厚非。

    对于字段的话,本质上就是去set这个字段的值,即对对象进行实例化和赋值,例如下面代码:

    @Autowired
    ObjectTest objectTest;
    

    那么在这里实现的就相当于给这个objecTest引用赋值了。

    对于方法的话,本质就是去调用这个方法,因此这里调用的是method.invoke.

    getResourceToInject方法的参数就是要注入的bean的名字,这个方法的功能就是根据这个bean的名字去拿到它。

    以上,就是@Autowire注解实现逻辑的全部分析。结合源代码再看一遍的话,会更加清楚一点。下面是spring容器如何实现@AutoWired自动注入的过程的图:

    image

    总结起来一句话:使用@Autowired注入的bean对于目标类来说,从代码结构上来讲也就是一个普通的成员变量,@Autowired和spring一起工作,通过反射为这个成员变量赋值,也就是将其赋为期望的类实例。

    Autowired注解的一些延伸问题

    注解的有效周期是什么?

    各种注释之间的第一个主要区别是,它们是在编译时使用,然后被丢弃(如@Override),还是被放在编译的类文件中,并在运行时可用(如Spring的@Component)。这是由注释的“@Retention”策略决定的。如果您正在编写自己的注释,则需要决定该注释在运行时(可能用于自动配置)还是仅在编译时(用于检查或代码生成)有用。

    当用注释编译代码时,编译器看到注释就像看到源元素上的其他修饰符一样,比如访问修饰符(public/private)或.。当遇到注释时,它运行一个注释处理器,就像一个插件类,表示对特定的注释感兴趣。注释处理器通常使用反射API来检查正在编译的元素,并且可以简单地对它们执行检查、修改它们或生成要编译的新代码。@Override是一个示例;它使用反射API来确保能够在其中一个超类中找到方法签名的匹配,如果不能,则使用@Override会导致编译错误。

    注入的bean和用它的bean的关系是如何维护的?

    无论以何种方式注入,注入的bean就相当于类中的一个普通对象应用,这是它的实例化是spring去容器中找符合的bean进行实例化,并注入到类当中的。他们之间的关系就是普通的一个对象持有另一个对象引用的关系。只是这些对象都是spring当中的bean而已。

    为什么注入的bean不能被定义为static的?

    从设计的角度来说 ,使用静态字段会鼓励使用静态方法。 静态方法是evil的。 依赖注入的主要目的是让容器为您创建对象并进行连接。 而且,它使测试更加容易。

    一旦开始使用静态方法,您就不再需要创建对象的实例,并且测试变得更加困难。 同样,您不能创建给定类的多个实例,每个实例都注入不同的依赖项(因为该字段是隐式共享的,并且会创建全局状态)。

    静态变量不是Object的属性,而是Class的属性。 spring的autowire是在对象上完成的,这样使得设计很干净。 在spring当中我们也可以将bean对象定义为单例,这样就能从功能上实现与静态定义相同的目的。

    但是从纯粹技术的层面,我们可以这样做:

    将@Autowired可以与setter方法一起使用,然后可以让setter修改静态字段的值。但是这种做法非常不推荐

    @Resource,@Autowired,@Inject 区别

    @Resource,@Autowired,@Inject 这3种都是用来注入bean的。

    但它们属于不同的程序中,区别详情参见下表:

    ANNOTATION PACKAGE SOURCE 作用域 实现方式 其它
    @AutoWired org.springframework.bean.factory,Spring自带的方式 Spring 2.5+ 可以用在构造器、方法、属性、参数、注解上面 通过AutowireAnnotationBeanPostProcessor类实现依赖注入 注入可以根据名字/类型,可以设置required属性为false指定找不到相应bean时不抛异常
    @Resource javax.annotation,是JSR-250标准,JDK6以上自带,Spring版本要求2.5以上 Java JSR-250 可以用在方法、属性、类上 通过CommonAnnotationBeanPostProcessor类实现依赖注入 与@AutoWired一致。但可以指定name属性来指定beanName,但如果name对应的bean不存在,则会抛出异常,且没有required属性
    @Inject javax.inject,是JSR-303标准,Spring版本3以上。需要导入外部依赖 Java JSR-330 可以用在方法、属性、构造器上 通过AutowiredAnnotationBeanPostProcessor类实现依赖注入 与@AutoWired一致,区别在于@Inject没有required属性

    @Inject

    如下是@Inject的使用,不加@Named注解,需要配置与变量名一致即可。

        @Inject
        @Named("mongo")
        private Mongo mongo;
    

    @Autowired

    @Autowired有个属性为required,可以配置为false,如果配置为false之后,当没有找到相应bean的时候,系统不会抛错。

        @Autowired
        private MongoTemplate mongoTemplate;
    

    @Resource

    @Resource一般会指定一个name属性,如下

        @Resource(name = "testMapper")
        private TestMapper testMapper;
    

    相关文章

      网友评论

        本文标题:SpringBoot @Autowired解析

        本文链接:https://www.haomeiwen.com/subject/hlmabktx.html