iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >dubbo之@Reference注解有什么作用
  • 105
分享到

dubbo之@Reference注解有什么作用

2023-07-05 14:07:08 105人浏览 薄情痞子
摘要

这篇文章主要介绍“dubbo之@Reference注解有什么作用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“dubbo之@Reference注解有什么作用”文章能帮助大家解决问题。目的看看dubb

这篇文章主要介绍“dubbo之@Reference注解有什么作用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“dubbo之@Reference注解有什么作用”文章能帮助大家解决问题。

    目的

    看看dubbo是怎么给加了@Reference注解的属性注入invoker实例,为什么有时候加了@Reference注解的属性会是null。

    ReferenceAnnotationBeanPostProcessor

    看到这个名字,就很容易知道,是专门针对@Reference注解的后置处理。

    ReferenceAnnotationBeanPostProcessor的代码比较多,下面列一下比较重要的内容。

    public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, ApplicationContextAware, BeanClassLoaderAware,        DisposableBean {    // 缓存加了@Referece注解的元数据信息,key是bean的名称或者类名,value是加了@Reference的属性和方法    private final ConcurrentMap<String, ReferenceInjectionMetadata> injectionMetadataCache =            new ConcurrentHashMap<String, ReferenceInjectionMetadata>(256);// 缓存new过的ReferenceBean,相同的key,只会产生一个ReferenceBean    private final ConcurrentMap<String, ReferenceBean<?>> referenceBeansCache =            new ConcurrentHashMap<String, ReferenceBean<?>>();// spring设置属性到bean之前调用该方法    @Override    public PropertyValues postProcessPropertyValues(            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {// 根据bean的类型,获取需要注入的元数据信息        InjectionMetadata metadata = findReferenceMetadata(beanName, bean.getClass(), pvs);        try {            // 注入对象            metadata.inject(bean, beanName, pvs);        } catch (BeanCreationException ex) {            throw ex;        } catch (Throwable ex) {            throw new BeanCreationException(beanName, "Injection of @Reference dependencies failed", ex);        }        return pvs;    }  private InjectionMetadata findReferenceMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {        // 如果是自定义的消费者,没有beanName,退化成使用类名作为缓存key        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());        // 双重检查,判断是否需要刷新注入信息        ReferenceInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);        // 判断是否需要刷新        if (InjectionMetadata.needsRefresh(metadata, clazz)) {        // 第一次判断为需要刷新,则住injectionMetadataCache对象            synchronized (this.injectionMetadataCache) {            // 再次判断是否需要刷新                metadata = this.injectionMetadataCache.get(cacheKey);                if (InjectionMetadata.needsRefresh(metadata, clazz)) {                // 需要刷新,而且原来缓存的信息不为空,清除缓存信息                    if (metadata != null) {                        metadata.clear(pvs);                    }                    try {                    // 生成新的元数据信息                        metadata = buildReferenceMetadata(clazz);                        // 放入缓存                        this.injectionMetadataCache.put(cacheKey, metadata);                    } catch (NoClassDefFoundError err) {                        throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +                                "] for reference metadata: could not find class that it depends on", err);                    }                }            }        }        return metadata;    }    private ReferenceInjectionMetadata buildReferenceMetadata(final Class<?> beanClass) {    // 查找加了@Reference注解的属性        Collection<ReferenceFieldElement> fieldElements = findFieldReferenceMetadata(beanClass);        // 查找加了@Reference注解的属性        // !!!!@Reference还能加到方法上!!!还真没试过        // 不过这个不关心,只关注属性的        Collection<ReferenceMethodElement> methodElements = findMethodReferenceMetadata(beanClass);        return new ReferenceInjectionMetadata(beanClass, fieldElements, methodElements);    }    private List<ReferenceFieldElement> findFieldReferenceMetadata(final Class<?> beanClass) {// 保存加了@Reference注解的属性列表        final List<ReferenceFieldElement> elements = new LinkedList<ReferenceFieldElement>();        ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {            @Override            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {// 获取属性上的@Reference注解                Reference reference = getAnnotation(field, Reference.class);// 如果存在@Reference注解                if (reference != null) {// 不支持静态属性的注入                    if (Modifier.isStatic(field.getModifiers())) {                        if (logger.isWarnEnabled()) {                            logger.warn("@Reference annotation is not supported on static fields: " + field);                        }                        return;                    }// 添加到队列里                    elements.add(new ReferenceFieldElement(field, reference));                }            }        });        return elements;    }

    ReferenceInjectionMetadata

    dubbo在ReferenceAnnotationBeanPostProcessor里定义了一个私有的子类

    ReferenceInjectionMetadata继承spring定义的InjectionMetadata类。

    之所以需要自定义ReferenceInjectionMetadata类,是因为dubbo的@Reference注解可以使用在属性和方法上,需要区分开。但是spring定义的InjectionMetadata类,只支持一个injectedElements集合,代码如下:

    public class InjectionMetadata {private static final Log logger = LogFactory.getLog(InjectionMetadata.class);private final Class<?> targetClass;private final Collection<InjectedElement> injectedElements;@Nullableprivate volatile Set<InjectedElement> checkedElements;public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {// 构造函数接收两个参数,类型,注入的元素this.targetClass = targetClass;this.injectedElements = elements;}    ......    ......    ......public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Collection<InjectedElement> checkedElements = this.checkedElements;// 优先使用checkedElements来注入,如果checkedElements为空,则直接使用injectedElements(没有调用checkConfigMembers方法,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);}}}

    基于这个原因,dubbo定义了ReferenceInjectionMetadata类,代码如下:

     private static class ReferenceInjectionMetadata extends InjectionMetadata {        private final Collection<ReferenceFieldElement> fieldElements;        private final Collection<ReferenceMethodElement> methodElements;        public ReferenceInjectionMetadata(Class<?> targetClass, Collection<ReferenceFieldElement> fieldElements,                                          Collection<ReferenceMethodElement> methodElements) {            // 构造函数接收3个参数,类型,待注入的属性元素,待注入的方法元素            // 把fieldElements和methodElements的内容合并,作为InjectionMetadata的injectedElements            super(targetClass, combine(fieldElements, methodElements));            this.fieldElements = fieldElements;            this.methodElements = methodElements;        }        private static <T> Collection<T> combine(Collection<? extends T>... elements) {            List<T> allElements = new ArrayList<T>();            for (Collection<? extends T> e : elements) {                allElements.addAll(e);            }            return allElements;        }        public Collection<ReferenceFieldElement> getFieldElements() {            return fieldElements;        }        public Collection<ReferenceMethodElement> getMethodElements() {            return methodElements;        }    }

    代码很简单,入参变为3个,属性和方法列表区分开,然后把两者合并起来,调用父类的构造函数,用fieldElements保存属性列表,用methodElements保存方法列表。

    ReferenceFieldElement

    属性注入实际发生在ReferenceFieldElement类,代码如下:

     private class ReferenceFieldElement extends InjectionMetadata.InjectedElement {        private final Field field;        private final Reference reference;        private volatile ReferenceBean<?> referenceBean;        // 构造函数会传入要设置的Field对象,Reference注解对象        protected ReferenceFieldElement(Field field, Reference reference) {            super(field, null);            this.field = field;            this.reference = reference;        }        @Override        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {            Class<?> referenceClass = field.getType();// 构建ReferenceBean对象            referenceBean = buildReferenceBean(reference, referenceClass);// 将属性设置为可访问的            ReflectionUtils.makeAccessible(field);// 给Field对象设置属性            field.set(bean, referenceBean.getObject());        }    }

    ReferenceMethodElement

    方法注入实际发生在ReferenceMethodElement类,代码如下:

    private class ReferenceMethodElement extends InjectionMetadata.InjectedElement {        private final Method method;        private final Reference reference;        private volatile ReferenceBean<?> referenceBean;        protected ReferenceMethodElement(Method method, PropertyDescriptor pd, Reference reference) {            super(method, pd);            this.method = method;            this.reference = reference;        }        @Override        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {// 获取类型            Class<?> referenceClass = pd.getPropertyType();// 构建ReferenceBean对象            referenceBean = buildReferenceBean(reference, referenceClass);// 将方法设置为可访问            ReflectionUtils.makeAccessible(method);// 把referenceBean生成的对象作为入参,调用bean对象的method方法// 看到这里,就能明白,@Reference也可以加在那些setXXX方法上// 例如有个userService属性,有个setUserService方法,可以在setUserService方法上加@Reference注解            method.invoke(bean, referenceBean.getObject());        }    }

    为什么加了@Reference注解的属性是null

    从上面的代码分析,可以知道属性的注入,是靠ReferenceAnnotationBeanPostProcessor后置处理来触发,往filed设置值。

    如果这一过程中,发生异常,导致没有成功为field设置值,则加了@Referencce的属性就会一直是null。

    2020-07-30 17:00:00.013  WARN 13092 --- [           main] com.alibaba.dubbo.config.AbstractConfig  : []  [DUBBO] null, dubbo version: 2.6.2, current host: 10.0.45.150

    java.lang.reflect.InvocationTargetException: null
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.alibaba.dubbo.config.AbstractConfig.toString(AbstractConfig.java:474)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at com.alibaba.dubbo.config.spring.beans.factory.annotation.AbstractAnnotationConfigBeanBuilder.build(AbstractAnnotationConfigBeanBuilder.java:79)
        at com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.buildReferenceBean(ReferenceAnnotationBeanPostProcessor.java:385)
        at com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.access$100(ReferenceAnnotationBeanPostProcessor.java:65)
        at com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceFieldElement.inject(ReferenceAnnotationBeanPostProcessor.java:363)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
        at com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.postProcessPropertyValues(ReferenceAnnotationBeanPostProcessor.java:92)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1400)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
        at org.springframework.beans.factory.support.DefaultSingletonBeanReGIStry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1325)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1171)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
        at org.springframework.boot.WEB.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at com.xdchen.bp.award.api.server.Application.main(Application.java:20)
    Caused by: java.lang.IllegalStateException: Failed to check the status of the service com.xdchen.searchplatfORM.searcher.protocol.SearcherService. No provider available for the service com.xdchen.searchplatform.searcher.protocol.SearcherService:1.0.0111 from the url ZooKeeper://zk1.esf.fdd:2181/com.alibaba.dubbo.registry.RegistryService?application=award.ddxf.bp.fdd&default.reference.filter=traceIdConsumer,default,consumerCatFilter&default.timeout=6000&dubbo=2.6.2&interface=com.xdchen.searchplatform.searcher.protocol.SearcherService&methods=search,searchByBytes,multiSearch,scrollIndex,searchByHttp,searchByIds,multiSearchByBytes&organization=fangdd&owner=chenxudong&pid=13092&register.ip=10.0.45.150&revision=3.8.0&side=consumer&timeout=5000&timestamp=1596099599500&version=1.0.0111 to the consumer 10.0.45.150 use dubbo version 2.6.2
        at com.alibaba.dubbo.config.ReferenceConfig.createProxy(ReferenceConfig.java:422)
        at com.alibaba.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:333)
        at com.alibaba.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:163)
        at com.alibaba.dubbo.config.spring.ReferenceBean.getObject(ReferenceBean.java:66)
        ... 42 common frames omitted

    2020-07-30 17:00:00.014  INFO 13092 --- [           main] c.a.d.c.s.b.f.a.ReferenceBeanBuilder     : [] <dubbo:reference singleton="true" interface="com.xdchen.searchplatform.searcher.protocol.SearcherService" uniqueServiceName="com.xdchen.searchplatform.searcher.protocol.SearcherService:1.0.0111" generic="false" version="1.0.0111" timeout="5000" id="com.xdchen.searchplatform.searcher.protocol.SearcherService" /> has been built.

    看这一段错误日志,当SearcherService没有任何provider启动的时候调用ReferenceBean.getObject方法,就会抛IllegalStateException异常,设置属性失败。

    网上很多说,遇到加@Reference注解的属性为null的,应该就是这个情况。

    什么情况会抛No provider的IllegalStateException异常

    ReferenceAnnotationBeanPostProcessor.buildReferenceBean

       private ReferenceBean<?> buildReferenceBean(Reference reference, Class<?> referenceClass) throws Exception {        String referenceBeanCacheKey = generateReferenceBeanCacheKey(reference, referenceClass);        ReferenceBean<?> referenceBean = referenceBeansCache.get(referenceBeanCacheKey);        if (referenceBean == null) {            ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder                    .create(reference, classLoader, applicationContext)                    .interfaceClass(referenceClass);// 这里报错            referenceBean = beanBuilder.build();            referenceBeansCache.putIfAbsent(referenceBeanCacheKey, referenceBean);        }        return referenceBean;    }

    buildReferenceBean方法调用ReferenceBeanBuilder.build报错

    ReferenceBeanBuilder.build

    ReferenceBeanBuilder.build方法是它的父类AbstractAnnotationConfigBeanBuilder的

     public final B build() throws Exception {        checkDependencies();        B bean = doBuild();        configureBean(bean);                if (logger.isInfoEnabled()) {        // 这里报错            logger.info(bean + " has been built.");        }        return bean;    }

    ReferenceBeanBuilder.doBuild

    ReferenceBeanBuilder重写了doBuild方法,返回ReferenceBean对象

        @Override    protected ReferenceBean doBuild() {        return new ReferenceBean<Object>();    }

    所以,问题是出在了ReferenceBean.toString方法上

    AbstractConfig.toString

    ReferenceBean并没有重写toString方法,但他的根父类是AbstractConfig,看错误日志,可以看到这个:

    at com.alibaba.dubbo.config.AbstractConfig.toString(AbstractConfig.java:474)

    AbstractConfig.toString代码如下:

     @Override    public String toString() {        try {            StringBuilder buf = new StringBuilder();            buf.append("<dubbo:");            buf.append(getTagName(getClass()));            Method[] methods = getClass().getMethods();            // 拿到当前类的所有方法            for (Method method : methods) {                try {                    String name = method.getName();                    // 过滤剩下get和is开头的方法,但不包括getClass、get和is                    if ((name.startsWith("get") || name.startsWith("is"))                            && !"getClass".equals(name) && !"get".equals(name) && !"is".equals(name)                            && Modifier.isPublic(method.getModifiers())                            && method.getParameterTypes().length == 0                            && isPrimitive(method.getReturnType())) {                        int i = name.startsWith("get") ? 3 : 2;                        String key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1);                        // 反射获取方法返回值,拼接字符串                        // 就是这里报空指针                        Object value = method.invoke(this, new Object[0]);                        if (value != null) {                            buf.append(" ");                            buf.append(key);                            buf.append("=\"");                            buf.append(value);                            buf.append("\"");                        }                    }                } catch (Exception e) {                    logger.warn(e.getMessage(), e);                }            }            buf.append(" />");            return buf.toString();        } catch (Throwable t) {            logger.warn(t.getMessage(), t);            return super.toString();        }    }

    ReferenceBean.getObjet

    ReferenceBean类实现类FactoryBean接口,实现了getObject方法,getObject方法满足get开头的条件,会被AbstractConfig.toString方法调用到

    public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {    @Override    public Object getObject() throws Exception {        return get();    }        public synchronized T get() {        if (destroyed) {            throw new IllegalStateException("Already destroyed!");        }        if (ref == null) {            init();        }        return ref;    }    private void init() {        if (initialized) {            return;        }        initialized = true;        ......        ......        ref = createProxy(map);        ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods());        ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel);    }    private T createProxy(Map<String, String> map) {        ............        Boolean c = check;        if (c == null && consumer != null) {            c = consumer.isCheck();        }        if (c == null) {            c = true; // default true        }        if (c && !invoker.isAvailable()) {            throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());        }        if (logger.isInfoEnabled()) {            logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());        }        // create service proxy        return (T) proxyFactory.getProxy(invoker);    }

    省略了大部分代码,只保留了比较重要的,调用getObject方法,会判断是否初始化过,如果初始化过,直接返回ref;如果没有初始化,则会进行初始化,然后调用createProxy方法来创建代理,如果我们没有配置consumer的check或者check=true,则会检查invoker对象的可用性“invoker.isAvailable()”,如果不可用,就会抛IllegalStateException异常。

    避免@Reference注解的属性为null

    配置消费者的检查为false,即@Reference(check=false)

    ReferenceBean.getObject调用时机的猜测

    看的ReferenceFieldElement.inject方法,很容易以为IllegalStateException是在 “field.set(bean, referenceBean.getObject());”这一行报错的,但实际上是在 “referenceBean = buildReferenceBean(reference, referenceClass);”

     @Override        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {            Class<?> referenceClass = field.getType();// 构建ReferenceBean对象            referenceBean = buildReferenceBean(reference, referenceClass);// 将属性设置为可访问的            ReflectionUtils.makeAccessible(field);// 给Field对象设置属性            field.set(bean, referenceBean.getObject());        }

    为什么要在AbstractConfig.toString就调用了getObject方法,触发报错呢?

    如果AbstractConfig.toString过滤掉getObject方法,会发生什么事情呢?

    InjectionMetadata.inject方法是遍历checkedElements列表,挨个调用element.inject方法。

    如果AbstractConfig.toString过滤掉getObject方法,则首次调用ReferenceBean.getObject方法是在“field.set(bean, referenceBean.getObject());”。异常没有被catch住,checkedElements列表的遍历会被打断。

    会出现这样的情况,有一个bean需要注入5个代理对象,但是调用第一个ReferenceBean.getObject的时候抛异常,则注入行为被中断,另外4个属性也没有被注入。

    关于“dubbo之@Reference注解有什么作用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

    --结束END--

    本文标题: dubbo之@Reference注解有什么作用

    本文链接: https://www.lsjlt.com/news/352318.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • dubbo之@Reference注解有什么作用
      这篇文章主要介绍“dubbo之@Reference注解有什么作用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“dubbo之@Reference注解有什么作用”文章能帮助大家解决问题。目的看看dubb...
      99+
      2023-07-05
    • dubbo之@Reference注解作用说明
      目录目的ReferenceAnnotationBeanPostProcessorReferenceInjectionMetadataReferenceFieldElementRefe...
      99+
      2023-03-21
      dubbo @Reference注解 @Reference注解作用 dubbo @Reference
    • RequestMapping注解有什么作用
      这篇“RequestMapping注解有什么作用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“RequestMapping注...
      99+
      2023-06-26
    • SpringMVC @RequestMapping注解有什么作用
      本篇内容介绍了“SpringMVC @RequestMapping注解有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、...
      99+
      2023-07-05
    • dubbo的spi机制有什么用途
      Dubbo的SPI(Service Provider Interface)机制可以实现插件化的扩展和灵活的配置,让用户可以在不修改源...
      99+
      2024-04-03
      dubbo
    • Spring声明式事务注解之@EnableTransactionManagement有什么用
      这篇文章给大家分享的是有关Spring声明式事务注解之@EnableTransactionManagement有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Spring声明式事务注解之@EnableTra...
      99+
      2023-06-20
    • restcontroller注解有什么用
      @RestController注解用于将一个类标识为Spring MVC的控制器,它的作用是:1. 自动将返回的数据转化为特定格式(...
      99+
      2023-08-20
      restcontroller
    • java注解的作用是什么
      本篇内容介绍了“java注解的作用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!说明注释是元数据,是源代码的元数据。注释为代码添加信息...
      99+
      2023-07-06
    • spring注解@Valid有什么用
      小编给大家分享一下spring注解@Valid有什么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!spring注解 @Valid 的作用在controller中...
      99+
      2023-06-29
    • SpringMVC注解之@ResponseBody注解原理是什么
      这篇文章主要介绍SpringMVC注解之@ResponseBody注解原理是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、介绍@ResponseBody 注解的作用是将方法的返回值通过适当的转换器转换为指定的...
      99+
      2023-06-15
    • Lombok基本注解之@SneakyThrows的作用
      使用范围: 只能作用在方法和构造函数之上 @SneakyThrows注解的作用得从java的异常设计体系说起。 java中常见的异常有两种: Exception即非运行时异常(编译...
      99+
      2024-04-02
    • java中注解的作用是什么
      这篇文章给大家介绍java中注解的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思...
      99+
      2023-06-14
    • java component注解的作用是什么
      Java组件注解的作用是为特定的类或方法提供元数据(metadata),以便在运行时进行处理。组件注解可以用于标记类、字段、方法或其...
      99+
      2023-09-23
      java
    • springboot常用注解及作用是什么
      Spring Boot 是基于 Spring 框架的快速开发框架,其中常用的注解及作用如下:1. @SpringBootApplic...
      99+
      2023-05-21
      springboot常用注解 springboot
    • 注册云服务器有什么作用
      注册云服务器的作用:可放置公司网站、电子商务平台、APP和其他应用程序等。使用云服务器来存储和共享数据,不仅高度安全,而且可以随时随地在线访问。当内存不够时,站长可自行增加,使资源充沛,保障了页面加载速度和优质的用户体验。...
      99+
      2024-04-02
    • Spring中@Import注解有什么用
      这期内容当中小编将会给大家带来有关Spring中@Import注解有什么用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。认识@Import注解@Target(ElementType.TYPE)@Reten...
      99+
      2023-06-15
    • Java中@RequestMapping注解有什么用
      这期内容当中小编将会给大家带来有关Java中@RequestMapping注解有什么用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、前言问题阐述:在某一场景下,我们的代码在 Service 实现相同,...
      99+
      2023-06-15
    • Spring中controlleradvice注解有什么用
      @ControllerAdvice注解在Spring中的使用有以下几个作用:1. 全局异常处理:使用@ControllerAdvic...
      99+
      2023-10-12
      Spring
    • Java中Annotation注解有什么用
      本篇文章给大家分享的是有关Java中Annotation注解有什么用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、概念  Annontation是Java5开始引入的新特征...
      99+
      2023-06-17
    • springmvc注解驱动的作用是什么
      Spring MVC注解驱动的作用是简化和加速开发过程,提高代码的可读性和可维护性。通过使用注解,可以避免繁琐的配置文件,减少开发人...
      99+
      2024-02-29
      springmvc
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作