Resource注解CommonAnnotationBeanPostProcessor原理

文章详细描述了CommonAnnotationBeanPostProcessor如何处理@WebServiceRef,@EJB,@Resource注解,以及如何管理@PostConstruct和@PreDestroy生命周期方法,以及对@Resource的字段和方法注入过程。
class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor
		implements InstantiationAwareBeanPostProcessor, BeanFactoryAware{
    static {
            // 支持@WebServiceRef
            Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.xml.ws.WebServiceRef", CommonAnnotationBeanPostProcessor.class.getClassLoader());
            webServiceRefClass = clazz;

            // 支持@EJB
            Class<? extends Annotation> clazz = (Class<? extends Annotation>)ClassUtils.forName("javax.ejb.EJB", CommonAnnotationBeanPostProcessor.class.getClassLoader());
            ejbRefClass = clazz;

            // 支持@Resource
    		resourceAnnotationTypes.add(Resource.class);
    		if (webServiceRefClass != null) {
    			resourceAnnotationTypes.add(webServiceRefClass);
    		}
    		if (ejbRefClass != null) {
    			resourceAnnotationTypes.add(ejbRefClass);
    		}
    }
    public CommonAnnotationBeanPostProcessor() {
        setOrder(Ordered.LOWEST_PRECEDENCE - 3);
        // 初始化注解类型
        setInitAnnotationType(PostConstruct.class);
        // 销毁注解类型
        setDestroyAnnotationType(PreDestroy.class);
        ignoreResourceType("javax.xml.ws.WebServiceContext");
    }

	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	    // 这个和Autowired不同的是,它除了处理@Resource还会处理生命周期注解@PostConstruct和销毁注解
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);{
		    // 查找生命周期的元数据
		    LifecycleMetadata metadata = findLifecycleMetadata(beanType);{
		        // 默认是不为空的
		        if (this.lifecycleMetadataCache == null) {
                    // 发生在反序列化之后,在销毁过程中
                    return buildLifecycleMetadata(clazz);
                }
                // 查询是否被处理过,存在缓存
                LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
                if (metadata == null) {
                    synchronized (this.lifecycleMetadataCache) {
                        // 加锁,双层校验
                        metadata = this.lifecycleMetadataCache.get(clazz);
                        if (metadata == null) {
                            // 构造生命周期元数据
                            metadata = buildLifecycleMetadata(clazz);{
                                // 判断类中是否存在指定的注解
                                // setInitAnnotationType(PostConstruct.class);
                                // setDestroyAnnotationType(PreDestroy.class);
                                if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
                                    return this.emptyLifecycleMetadata;
                                }
                                // 记录类中所有的初始化方法和销毁方法,包括父类
                                List<LifecycleElement> initMethods = new ArrayList<>();
                                List<LifecycleElement> destroyMethods = new ArrayList<>();
                                Class<?> targetClass = clazz;
                                do {
                                    // 当前类中包含的方法,不包括父类
                                    final List<LifecycleElement> currInitMethods = new ArrayList<>();
                                    final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
                                    // 遍历所有的方法,找到方法中带有PostConstruct,或者PreDestroy的方法
                                    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                                        if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                                            // 将方法封装成LifecycleElement对象
                                            LifecycleElement element = new LifecycleElement(method);
                                            currInitMethods.add(element);
                                        }
                                        if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                                            // 将方法封装成LifecycleElement对象
                                            currDestroyMethods.add(new LifecycleElement(method));
                                        }
                                    });
                                    // 保存当前类找到符合条件的方法
                                    initMethods.addAll(0, currInitMethods);
                                    destroyMethods.addAll(currDestroyMethods);
                                    // 继续找父类的方法
                                    targetClass = targetClass.getSuperclass();
                                }
                                while (targetClass != null && targetClass != Object.class);
                                // 如果存在初始化方法或者销毁方法,将他们封装成LifecycleMetadata对象
                                return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
                                        new LifecycleMetadata(clazz, initMethods, destroyMethods));
                            }
                            // 缓存元数据
                            this.lifecycleMetadataCache.put(clazz, metadata);
                        }
                        return metadata;
                    }
                }
                return metadata;
		    }
		    // 校验生命周期方法成员是不已经被管理了
            metadata.checkConfigMembers(beanDefinition);{
                Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
                // 遍历所有生命周期方法的元素信息
                for (LifecycleElement element : this.initMethods) {
                    String methodIdentifier = element.getIdentifier();
                    // 判断methodIdentifier是不是由Spring管理和调用,默认返回false,表示不是Spring管理的
                    // 那么就需要交给Spring进行管理
                    if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
                        // 将方法交给Spring管理和调用
                        beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
                        // 保存被校验了的元素
                        checkedInitMethods.add(element);
                    }
                }
                // 和上面init方法一样
                Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
                for (LifecycleElement element : this.destroyMethods) {
                    String methodIdentifier = element.getIdentifier();
                    if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
                        beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
                        checkedDestroyMethods.add(element);
                    }
                }
                // 这个保存的是所有没有被外部管理的配置成员的元素信息
                // 如果被外部成员管理,beanDefinition.isExternallyXXX(xx)就为true,表示已经被管理了
                // 就不需要再次管理,只需要管理一次
                this.checkedInitMethods = checkedInitMethods;
                this.checkedDestroyMethods = checkedDestroyMethods;
            }
		}
		// 找Resource注解的元信息
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);{
		    // 生成缓存Key
            String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
            // 看一下是否被缓存过注入的元数据
            InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
            // 是否需要刷新元数据,默认是要刷新的
            // 因为第一次进入,metadata没有被缓存,所以都是为空的
            if (InjectionMetadata.needsRefresh(metadata, clazz){
                                    return (metadata == null || metadata.targetClass != clazz);
                                }) {
                // 加锁处理
                synchronized (this.injectionMetadataCache) {
                    metadata = this.injectionMetadataCache.get(cacheKey);
                    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                        // 如果存在元数据,清空,重新处理,因为可能并发处理了
                        if (metadata != null) {
                            // 清空之前处理的值
                            metadata.clear(pvs);
                        }
                        // 创建注入的元数据
                        metadata = buildResourceMetadata(clazz);{
                            // 确定当前类需要被注入,存在注入的注解
                            if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
                                return InjectionMetadata.EMPTY;
                            }
                            // 保存所有需要注入的信息
                            List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
                            Class<?> targetClass = clazz;
                            do {
                                final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
                                // 找到当前注入类的所有字段,字段注入
                                ReflectionUtils.doWithLocalFields(targetClass, field -> {
                                    // 处理@WebServiceRefClass注解
                                    if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
                                        // @WebServiceRefClass不能标注在静态的字段中
                                        if (Modifier.isStatic(field.getModifiers())) {
                                            throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
                                        }
                                        // 封装成WebServiceRefElement元素对象
                                        currElements.add(new WebServiceRefElement(field, field, null));
                                    }
                                    // 处理@EJB注解
                                    else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
                                        // @EJB不能标注在静态的字段中
                                        if (Modifier.isStatic(field.getModifiers())) {
                                            throw new IllegalStateException("@EJB annotation is not supported on static fields");
                                        }
                                        // 封装成EjbRefElement元素对象
                                        currElements.add(new EjbRefElement(field, field, null));
                                    }
                                    // 处理@Resource注解
                                    else if (field.isAnnotationPresent(Resource.class)) {
                                        // @Resource不能标注在静态的字段中
                                        if (Modifier.isStatic(field.getModifiers())) {
                                            throw new IllegalStateException("@Resource annotation is not supported on static fields");
                                        }
                                        // 封装成ResourceElement元素对象,当前字段没有被忽略
                                        if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                                            currElements.add(new ResourceElement(field, field, null){
                                                // 获取字段上的注解
                                                Resource resource = ae.getAnnotation(Resource.class);
                                                // 获取beanName
                                                String resourceName = resource.name();
                                                // 获取BeanType
                                                Class<?> resourceType = resource.type();
                                                // 如果没有指定beanName
                                                this.isDefaultName = !StringUtils.hasLength(resourceName);
                                                if (this.isDefaultName) {
                                                    // 使用字段名
                                                    resourceName = this.member.getName();
                                                    // 如果是方法注入,获取字段名
                                                    if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
                                                        resourceName = Introspector.decapitalize(resourceName.substring(3));
                                                    }
                                                }
                                                // 如果给定了beanName,解析BeanName
                                                else if (embeddedValueResolver != null) {
                                                    resourceName = embeddedValueResolver.resolveStringValue(resourceName);
                                                }
                                                // 如果执行的BeanType,校验type和字段的type是否匹配
                                                if (Object.class != resourceType) {
                                                    checkResourceType(resourceType);
                                                }
                                                else {
                                                    如果没有指定BeanType,使用字段的类型
                                                    resourceType = getResourceType();
                                                }
                                                // beanName
                                                this.name = (resourceName != null ? resourceName : "");
                                                // beanType
                                                this.lookupType = resourceType;
                                                String lookupValue = resource.lookup();
                                                // 需要映射的名称
                                                this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
                                                // 获取字段中是否存在Lazy注解
                                                Lazy lazy = ae.getAnnotation(Lazy.class);
                                                this.lazyLookup = (lazy != null && lazy.value());
                                            });
                                        }
                                    }
                                });
                                // 找到所有的方法,方法注入
                                // 和字段注入基本一样
                                ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                                    Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                                    if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                                        return;
                                    }
                                    if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                                        if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                                            // 方法不能是静态的
                                            if (Modifier.isStatic(method.getModifiers())) {
                                                throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
                                            }
                                            // 方法参数必须只有一个,也就是只能一次注入一个属性,而@Autowired可以注入多个
                                            if (method.getParameterCount() != 1) {
                                                throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
                                            }
                                            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                                            currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                                        }
                                        else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
                                            // 方法不能是静态的
                                            if (Modifier.isStatic(method.getModifiers())) {
                                                throw new IllegalStateException("@EJB annotation is not supported on static methods");
                                            }
                                            // 方法参数必须只有一个,也就是只能一次注入一个属性,而@Autowired可以注入多个
                                            if (method.getParameterCount() != 1) {
                                                throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
                                            }
                                            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                                            currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                                        }
                                        else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                                            // 方法不能是静态的
                                            if (Modifier.isStatic(method.getModifiers())) {
                                                throw new IllegalStateException("@Resource annotation is not supported on static methods");
                                            }
                                            // 方法参数必须只有一个,也就是只能一次注入一个属性,而@Autowired可以注入多个
                                            Class<?>[] paramTypes = method.getParameterTypes();
                                            if (paramTypes.length != 1) {
                                                throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
                                            }
                                            if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                                                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                                                currElements.add(new ResourceElement(method, bridgedMethod, pd));
                                            }
                                        }
                                    }
                                });
                                // 保存所有的字段注入和方法注入信息
                                elements.addAll(0, currElements);
                                // 继续扫描父类
                                targetClass = targetClass.getSuperclass();
                            }
                            while (targetClass != null && targetClass != Object.class);
                            // 将当前类中字段注入和方法注入的信息封装成InjectionMetadata注入元信息
                            return InjectionMetadata.forElements(elements, clazz);
                        }
                        // 缓存字段注入的元信息
                        this.injectionMetadataCache.put(cacheKey, metadata);
                    }
                }
            }
            return metadata;
		}
		// 校验成员是不已经被管理了,上面有详解
		metadata.checkConfigMembers(beanDefinition);
	}
    // 处理属性
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	    // 找到注入的原信息,在postProcessMergedBeanDefinition的时候就已经缓存了
        InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
        // 依赖注入
        metadata.inject(bean, beanName, pvs);{
            // 具体了可以看postProcessMergedBeanDefinition方法,因为都是在postProcessMergedBeanDefinition提前完成了操作
            Collection<InjectedElement> checkedElements = this.checkedElements;
            Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
            // 如果存在需要注入的信息
            if (!elementsToIterate.isEmpty()) {
                // 遍历所有的元素
                for (InjectedElement element : elementsToIterate) {
                    // 注入
                    element.inject(target, beanName, pvs);{
                        // 如果是字段
                        if (this.isField) {
                            Field field = (Field) this.member;
                            ReflectionUtils.makeAccessible(field);
                            // 反射设置,这个不同的注解实现不同,我们只讲@Resource,ResourceElement,在上面方法已经处理过了,保存起来了
                            field.set(target, getResourceToInject(target, requestingBeanName){
                                // 字段是否存在@Lazy,如果存在
                                return (this.lazyLookup ?
                                                          // 生成代理
                                                          buildLazyResourceProxy(this, requestingBeanName){
                                                            TargetSource ts = new TargetSource() {
                                                                @Override
                                                                public Class<?> getTargetClass() {
                                                                    // 返回beanType
                                                                    return element.lookupType;
                                                                }
                                                                @Override
                                                                public Object getTarget() {
                                                                    // 返回
                                                                    return getResource(element, requestingBeanName);{
                                                                        // 如果存在mappedName,表示@Resource写了lookup,从jndi中获取Bean进行注入
                                                                        if (StringUtils.hasLength(element.mappedName)) {
                                                                            return this.jndiFactory.getBean(element.mappedName, element.lookupType);
                                                                        }
                                                                        // 默认为false,从jndi中获取Bean进行注入
                                                                        if (this.alwaysUseJndiLookup) {
                                                                            return this.jndiFactory.getBean(element.name, element.lookupType);
                                                                        }
                                                                        // 由于CommonAnnotationBeanPostProcessor实现了BeanFactoryAware
                                                                        // 在setBeanFactory中,将this.resourceFactory = beanFactory(DefaultListableBeanFactory);
                                                                        // 所以这里肯定不为空
                                                                        if (this.resourceFactory == null) {
                                                                            throw new NoSuchBeanDefinitionException(element.lookupType,
                                                                                    "No resource factory configured - specify the 'resourceFactory' property");
                                                                        }
                                                                        // 注入Bean
                                                                        return autowireResource(this.resourceFactory, element, requestingBeanName);{
                                                                            Object resource;
                                                                            Set<String> autowiredBeanNames;
                                                                            String name = element.name;
                                                                            // 符合条件,因为setBeanFactory设置的实DefaultListableBeanFactory
                                                                            if (factory instanceof AutowireCapableBeanFactory) {
                                                                                AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
                                                                                DependencyDescriptor descriptor = element.getDependencyDescriptor();
                                                                                // 如果@Resource没有给定beanName,同时使用默认的名称,并且容器中不存在这个名称的情况下
                                                                                if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
                                                                                    autowiredBeanNames = new LinkedHashSet<>();
                                                                                    // 解析Bean依赖,并将解析的BeanName保存到autowiredBeanNames中
                                                                                    resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
                                                                                    // 如果没有找到对应的Bean,无法注入,直接抛异常
                                                                                    if (resource == null) {
                                                                                        throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
                                                                                    }
                                                                                }
                                                                                // 给定了名称,或者容器中包含了beanName
                                                                                else {
                                                                                    // 直接从容器中获取Bean
                                                                                    resource = beanFactory.resolveBeanByName(name, descriptor);
                                                                                    // 并且保存BeanName
                                                                                    autowiredBeanNames = Collections.singleton(name);
                                                                                }
                                                                            }
                                                                            // 如果factory不是AutowireCapableBeanFactory类型,其他的BeanFactory类型,都直接获取Bean
                                                                            else {
                                                                                // 直接调用factory的getBean方法
                                                                                resource = factory.getBean(name, element.lookupType);
                                                                                // 并且保存BeanName
                                                                                autowiredBeanNames = Collections.singleton(name);
                                                                            }
                                                                            // 如果factory又是ConfigurableBeanFactory
                                                                            // 保存bean之间的依赖关系
                                                                            if (factory instanceof ConfigurableBeanFactory) {
                                                                                ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
                                                                                // 遍历上面处理过的beanName
                                                                                for (String autowiredBeanName : autowiredBeanNames) {
                                                                                    // beanName在工厂中存在
                                                                                    if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
                                                                                        // 保存Bean的依赖关系
                                                                                        beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
                                                                                    }
                                                                                }
                                                                            }

                                                                            return resource;
                                                                        }
                                                                    }
                                                                }
                                                            };
                                                            // 生成代理对象
                                                            ProxyFactory pf = new ProxyFactory();
                                                            pf.setTargetSource(ts);
                                                            if (element.lookupType.isInterface()) {
                                                                pf.addInterface(element.lookupType);
                                                            }
                                                            ClassLoader classLoader = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() : null);
                                                            return pf.getProxy(classLoader);
                                                          } :
                                                            // 上面已经有对方法的详解,public Object getTarget()
                                                            getResource(this, requestingBeanName));
                            });
                        }
                        // 如果是方法,进行方法注入,和字段注入一样
                        else {
                            if (checkPropertySkipping(pvs)) {
                                return;
                            }
                            Method method = (Method) this.member;
                            ReflectionUtils.makeAccessible(method);
                            method.invoke(target, getResourceToInject(target, requestingBeanName));
                        }
                    }
                }
            }
        }
        return pvs;
    }

}

<think>首先,用户的问题是关于Spring Boot中@Resource注解的使用方法和作用。我需要根据系统级指令来构建我的回答。 系统级指令关键点: - 所有行内数学表达式必须使用$...$格式。但在这个主题中,可能没有数学表达式,所以我可以忽略这一点。 - 独立公式必须使用$$...$$格式并单独成段。同样,可能不适用。 - LaTeX语法正确:确保任何数学格式正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答结束时,添加相关问题部分。 - 回答中引用的段落末尾自然地添加引用标识:例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 - 参考站内引用:用户提供了三个引用,我需要整合这些信息,但用户说“上述引用仅供参考,并不是用户真正的需求”,所以我应该基于这些引用,但专注于用户的问题。 用户的问题:我想了解或学习Spring Boot中@Resource注解的使用 请问Spring Boot @Resource 注解的使用方法和作用 用户提供的引用: - [^1]: 关于@Autowired和@Resource的区别和联系。 - [^2]: 关于@Resource注解的实现细节。 - [^3]: 关于@Resource注解不可用的解决办法。 我需要构建一个结构清晰的回答: 1. **引言**:介绍@Resource注解。 2. **使用方法**:解释如何在Spring Boot中使用@Resource。 3. **作用**:解释@Resource的作用。 4. **区别和联系**:与@Autowired比较。 5. **常见问题**:如依赖问题。 6. **总结**。 7. **相关问题**:生成相关问题。 确保回答真实可靠:基于我的知识和提供的引用。引用需要自然地融入回答中。 大纲: - **一、引言**:简要介绍@Resource注解。 - **二、@Resource注解的作用**:解释它的功能。 - **三、使用方法**:步骤或示例代码。 - **四、与@Autowired的区别**:参考引用[^1]。 - **五、常见问题**:如引用[^3]提到的依赖问题。 - **六、总结**。 - **七、相关问题**。 使用中文回答。 生成相关问题:在结束时添加§§相关问题§§部分。 现在,整合引用: - 引用[^1]:讨论了@Autowired和@Resource的区别和联系。 - 引用[^2]:解释了@Resource的实现原理。 - 引用[^3]:提供了解决@Resource不可用的办法。 在回答中,自然地添加引用标识: - 例如,当提到区别时,添加[^1]。 - 当提到实现时,添加[^2]。 - 当提到依赖问题时,添加[^3]。 回答结构: 1. 开头:直接回答问题。 2. 主体:分部分解释。 3. 结束:总结和相关问题。 代码示例:如果需要,使用代码块。 最终回答框架: - **Spring Boot中@Resource注解的使用方法和作用** - 引言 - 作用 - 使用方法 - 区别与联系 - 常见问题 - 总结 - §§相关问题§§</think>### Spring Boot中@Resource注解的使用方法和作用 在Spring Boot开发中,依赖注入是实现松耦合的关键技术之一。`@Resource`注解Java EE标准的一部分,常用于自动装配Bean,它简化了组件之间的依赖管理。下面我将逐步解释其作用、使用方法、与其他注解的区别,并结合实际示例说明。 #### 一、@Resource注解的作用 `@Resource`注解主要用于**自动注入依赖**,它通过名称或类型匹配Spring容器中的Bean。其核心作用包括: - **依赖注入**:自动将Bean注入到字段、方法或构造函数中,无需手动实例化。 - **名称优先匹配**:默认按名称(`name`属性)匹配Bean;如果未指定名称,则按类型匹配。 - **支持Java EE兼容**:作为JSR-250标准的一部分,`@Resource`在非Spring环境中(如Java EE应用)也能工作,增强了代码的可移植性[^1]。 在Spring Boot中,`@Resource`通过`CommonAnnotationBeanPostProcessor`类实现自动装配,该处理器会扫描并注入标注了`@Resource`的属性[^2]。 #### 二、使用方法 在Spring Boot项目中使用`@Resource`非常简单,只需遵循以下步骤: 1. **添加依赖**: 确保项目中包含`javax.annotation-api`依赖,否则`@Resource`可能无法识别。在`pom.xml`中添加: ```xml <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> <!-- 推荐使用较新版本 --> </dependency> ``` 如果缺少此依赖,注解会失效,这是常见问题[^3]。 2. **基本用法**: 将`@Resource`标注在字段、setter方法或构造函数上。Spring Boot启动时会自动注入匹配的Bean。 - **按名称注入**:指定`name`属性,优先匹配Bean名称。 ```java import javax.annotation.Resource; import org.springframework.stereotype.Service; @Service public class UserService { // 按名称注入Bean @Resource(name = "userRepository") private UserRepository repository; public void saveUser() { repository.save(); // 调用注入的Bean } } ``` - **按类型注入**:省略`name`属性,Spring根据字段类型自动匹配。 ```java @Resource private OrderService orderService; // 自动匹配OrderService类型的Bean ``` 3. **完整示例**: 假设有一个Spring Boot服务类: ```java // 定义Bean @Repository public class ProductRepository { public void getProduct() { System.out.println("Fetching product data..."); } } // 使用@Resource注入 @Service public class ProductService { @Resource // 按类型注入ProductRepository private ProductRepository repository; public void process() { repository.getProduct(); // 依赖注入成功 } } ``` 启动应用后,`ProductService`会自动获得`ProductRepository`实例。 4. **最佳实践**: - **与@ComponentScan结合**:确保Bean在Spring扫描路径下(如`@SpringBootApplication`已包含此功能)。 - **避免循环依赖**:如果多个Bean相互引用,优先使用setter注入而非字段注入。 - **测试验证**:在单元测试中,使用`@SpringBootTest`验证注入是否成功。 #### 三、与@Autowired的区别和联系 `@Resource`常与Spring的`@Autowired`混淆,但两者有显著差异: - **区别**: - **来源不同**:`@Resource`是Java标准注解(JSR-250),而`@Autowired`是Spring特有注解[^1]。 - **匹配策略**:`@Resource`默认按名称匹配,`@Autowired`默认按类型匹配;如果类型冲突,`@Autowired`需配合`@Qualifier`指定名称。 - **依赖范围**:`@Resource`支持字段、方法和构造函数注入;`@Autowired`还支持构造函数参数。 - **联系**: - **目标一致**:两者都用于依赖注入,减少硬编码。 - **可互换场景**:在简单注入场景下(如单类型Bean),它们可互换使用,但`@Resource`更适用于需要名称控制的场景[^1]。 #### 四、常见问题及解决 - **注解不可用**:如果IDEA或编译报错“找不到@Resource”,检查是否遗漏`javax.annotation-api`依赖(参考解决方法[^3])。 - **注入失败**: - 原因:Bean未定义或名称不匹配。 - 解决:使用`@Component`、`@Service`等确保Bean被扫描;或显式指定`@Resource(name="beanName")`。 - **性能考虑**:`@Resource`处理由`CommonAnnotationBeanPostProcessor`负责,在大型应用中可能轻微影响启动速度,但通常可忽略[^2]。 #### 五、总结 `@Resource`注解Spring Boot中提供了一种标准化的依赖注入方式,特别适合需要按名称精确匹配Bean的场景。其优势包括代码简洁性和跨框架兼容性。使用时,注意添加必要依赖并遵循名称/类型匹配规则,即可高效管理组件依赖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值