日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

从源码层面带你实现一个自动注入注解

發(fā)布時(shí)間:2025/1/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从源码层面带你实现一个自动注入注解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如何自己實(shí)現(xiàn)一個(gè)自動(dòng)注入的注解


  • 首先,需要了解到的是。Spring Bean 的生命周期
  • 在生命周期中。注入bean屬性的位置是在以下代碼:populateBean?位置中
  • 那么我們?cè)陧?xiàng)目中使用注解 產(chǎn)生一個(gè)bean的時(shí)候必定會(huì)經(jīng)過(guò)以下代碼進(jìn)行一個(gè)bean的創(chuàng)建流程
/**省略代碼**/ // 開始初始化 bean 實(shí)例對(duì)象 Object exposedObject = bean; try {// <5> 對(duì) bean 進(jìn)行填充,將各個(gè)屬性值注入,其中,可能存在依賴于其他 bean 的屬性populateBean(beanName, mbd, instanceWrapper);// <6> 調(diào)用初始化方法exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);} } /**省略代碼**/
  • 在生命周期中 populateBean 進(jìn)行填充bean數(shù)據(jù)。把其他依賴引入進(jìn)來(lái)
  • BeanPostProcessor 是一個(gè)bean創(chuàng)建時(shí)候的一個(gè)鉤子。
  • 以下代碼 是循環(huán)調(diào)用實(shí)現(xiàn)了 BeanPostProcessor 子類?InstantiationAwareBeanPostProcessor#postProcessProperties?方法
  • Spring 在以下代碼中有自動(dòng)注入的拓展點(diǎn)。 關(guān)鍵就是實(shí)現(xiàn)?InstantiationAwareBeanPostProcessor#postProcessProperties
/**省略代碼**/ for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// 對(duì)所有需要依賴檢查的屬性進(jìn)行后處理PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {// 從 bw 對(duì)象中提取 PropertyDescriptor 結(jié)果集// PropertyDescriptor:可以通過(guò)一對(duì)存取方法提取一個(gè)屬性if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;} } /**省略代碼**/
  • 我們展開來(lái)講一下 @Autowired 的實(shí)現(xiàn)是怎么樣的吧:
  • 實(shí)現(xiàn)類為?AutowiredAnnotationBeanPostProcessor.java
  • 從上面可以得知,填充bean的時(shí)候。時(shí)調(diào)用了方法?ibp.postProcessPropertyValues()
  • 那么?AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues()?則會(huì)被調(diào)用
  • 調(diào)用?findAutowiringMetadata?獲取 class 以及父類 帶有?@Autowired?或者?@Value?的屬性或者方法:
/**省略代碼**/ public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 獲取所有可以注入的元數(shù)據(jù)InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);try {// 注入數(shù)據(jù)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; } private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {// 緩存名字獲取String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);// 獲取是否已經(jīng)讀取過(guò)這個(gè) class 類的 InjectionMetadata 有的話直接從緩存中獲取出去if (InjectionMetadata.needsRefresh(metadata, clazz)) {synchronized (this.injectionMetadataCache) {// 雙重檢查metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {if (metadata != null) {metadata.clear(pvs);}// 構(gòu)建自動(dòng)注入的元數(shù)據(jù)metadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata; } private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// 循環(huán) targetClass 的所有 field 并執(zhí) FieldCallback 邏輯 (函數(shù)式編程接口,傳入的是一個(gè)執(zhí)行函數(shù))ReflectionUtils.doWithLocalFields(targetClass, field -> {// 獲得字段上面的 Annotation 注解MergedAnnotation<?> ann = findAutowiredAnnotation(field);if (ann != null) {// 判斷是否為靜態(tài)屬性 如果是,則不進(jìn)行注入if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;}// 注解是否為必須依賴項(xiàng)boolean required = determineRequiredStatus(ann);currElements.add(new AutowiredFieldElement(field, required));}});// 循環(huán) targetClass 的所有 Method 并執(zhí) MethodCallback 邏輯 (函數(shù)式編程接口,傳入的是一個(gè)執(zhí)行函數(shù))ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {// 判斷是否為靜態(tài)方法 如果是,則不進(jìn)行注入if (Modifier.isStatic(method.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static methods: " + method);}return;}// 判斷靜態(tài)方法參數(shù)是否為0if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("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));}});//數(shù)據(jù)加到數(shù)組最前方 父類的的注解都放在靠前的位置elements.addAll(0, currElements);// 如果有父類則設(shè)置 targetClass 為父類。 如此循環(huán)targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz); }/**省略代碼**/
  • 真正注入數(shù)據(jù)的是?metadata.inject(bean, beanName, pvs);
  • 調(diào)用的是?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) {element.inject(target, beanName, pvs);}} }
  • 循環(huán)調(diào)用之前加入的帶有注解的方法或者屬性構(gòu)建的對(duì)象?AutowiredFieldElement#inject,?AutowiredMethodElement#inject
/*** 屬性上有注解 構(gòu)建的處理對(duì)象*/private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {private final boolean required;private volatile boolean cached;@Nullableprivate volatile Object cachedFieldValue;public AutowiredFieldElement(Field field, boolean required) {super(field, null);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 獲取屬性名Field field = (Field) this.member;Object value;// Bean 不是單例的話,會(huì)重復(fù)進(jìn)入注入的這個(gè)操作,if (this.cached) {try {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}catch (NoSuchBeanDefinitionException ex) {// Unexpected removal of target bean for cached argument -> re-resolvevalue = resolveFieldValue(field, bean, beanName);}}else {// 首次創(chuàng)建的時(shí)候進(jìn)入該方法value = resolveFieldValue(field, bean, beanName);}if (value != null) {// 屬性如果不為public的話,則設(shè)置為可訪問(wèn)ReflectionUtils.makeAccessible(field);field.set(bean, value);}}@Nullableprivate Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {// 構(gòu)建DependencyDescriptor對(duì)象DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());// 注入bean的數(shù)量。 有可能字段上是一個(gè)ListSet<String> autowiredBeanNames = new LinkedHashSet<>(1);Assert.state(beanFactory != null, "No BeanFactory available");// 獲得beanFactory類型轉(zhuǎn)換類TypeConverter typeConverter = beanFactory.getTypeConverter();Object value;try {// 查找依賴關(guān)系value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}synchronized (this) {if (!this.cached) {Object cachedFieldValue = null;if (value != null || this.required) {cachedFieldValue = desc;// 填入依賴關(guān)系registerDependentBeans(beanName, autowiredBeanNames);// 判斷如果注入依賴是只有一個(gè)if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}this.cachedFieldValue = cachedFieldValue;this.cached = true;}}return value;}}/*** 方法上有注解 構(gòu)建的處理對(duì)象*/private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {private final boolean required;private volatile boolean cached;@Nullableprivate volatile Object[] cachedMethodArguments;public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {super(method, pd);this.required = required;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {// 檢查屬性是不會(huì)在之前就已經(jīng)注入過(guò)了。如果主如果則不進(jìn)行二次覆蓋if (checkPropertySkipping(pvs)) {return;}Method method = (Method) this.member;Object[] arguments;if (this.cached) {try {arguments = resolveCachedArguments(beanName);}catch (NoSuchBeanDefinitionException ex) {// Unexpected removal of target bean for cached argument -> re-resolvearguments = resolveMethodArguments(method, bean, beanName);}}else {// 首次創(chuàng)建的時(shí)候進(jìn)入該方法arguments = resolveMethodArguments(method, bean, beanName);}if (arguments != null) {try {// 屬性如果不為public的話,則設(shè)置為可訪問(wèn)ReflectionUtils.makeAccessible(method);// 調(diào)用方法 并傳入?yún)?shù)method.invoke(bean, arguments);}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}@Nullableprivate Object[] resolveCachedArguments(@Nullable String beanName) {Object[] cachedMethodArguments = this.cachedMethodArguments;if (cachedMethodArguments == null) {return null;}Object[] arguments = new Object[cachedMethodArguments.length];for (int i = 0; i < arguments.length; i++) {arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);}return arguments;}@Nullableprivate Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {// 獲取方法上有幾個(gè)參數(shù)int argumentCount = method.getParameterCount();Object[] arguments = new Object[argumentCount];DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();for (int i = 0; i < arguments.length; i++) {// 方法參數(shù),從方法參數(shù)中取出 i 構(gòu)造 MethodParameter 對(duì)象MethodParameter methodParam = new MethodParameter(method, i);DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);currDesc.setContainingClass(bean.getClass());descriptors[i] = currDesc;try {// 獲取方法中 i 參數(shù)的內(nèi)容Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);if (arg == null && !this.required) {arguments = null;break;}arguments[i] = arg;}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);}}synchronized (this) {if (!this.cached) {if (arguments != null) {DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);registerDependentBeans(beanName, autowiredBeans);if (autowiredBeans.size() == argumentCount) {Iterator<String> it = autowiredBeans.iterator();Class<?>[] paramTypes = method.getParameterTypes();for (int i = 0; i < paramTypes.length; i++) {String autowiredBeanName = it.next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]);}}}this.cachedMethodArguments = cachedMethodArguments;}else {this.cachedMethodArguments = null;}this.cached = true;}}return arguments;}}
  • 以上就是?@Autowired?實(shí)現(xiàn)的完整流程。 可概括為:
    populateBean?->?AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
    -> 獲取帶有注解的屬性和方法構(gòu)建?AutowiredFieldElement,?AutowiredMethodElement?對(duì)象,然后循環(huán)調(diào)用了?inject?進(jìn)行屬性調(diào)用

自定義自動(dòng)注入注解。

  • 編寫抽象類代碼:
package com.yunlongn.common.core.autowired;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.*; import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils;import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap;/*** 抽象的自動(dòng)注入方法* @author yunlgongn*/ public abstract class AbstractAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {private final Set<Class<? extends Annotation>> annotationTypes = new LinkedHashSet<>(4);private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);protected final Log logger = LogFactory.getLog(getClass());/*** 處理的 annotationType 對(duì)象* @return Annotation 自定義注解*/public abstract Class<? extends Annotation> annotationType();AbstractAnnotationBeanPostProcessor () {Class<? extends Annotation> annotation = this.annotationType();annotationTypes.add(annotation);}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {InjectionMetadata metadata = findAbstractMetadata(beanName, bean.getClass(), pvs);try {// 注入數(shù)據(jù)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;}private InjectionMetadata findAbstractMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);// 獲取是否已經(jīng)讀取過(guò)這個(gè) class 類的 InjectionMetadata 有的話直接從緩存中獲取出去if (InjectionMetadata.needsRefresh(metadata, clazz)) {synchronized (this.injectionMetadataCache) {// 雙重檢查metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {if (metadata != null) {metadata.clear(pvs);}metadata = buildAbstractMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;}private InjectionMetadata buildAbstractMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.annotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// 循環(huán) targetClass 的所有 field 并執(zhí) FieldCallback 邏輯 (函數(shù)式編程接口,傳入的是一個(gè)執(zhí)行函數(shù))ReflectionUtils.doWithLocalFields(targetClass, field -> {// 獲得字段上面的 Annotation 注解MergedAnnotation<?> ann = findAbstractAnnotation(field);if (ann != null) {// 判斷是否為靜態(tài)屬性 如果是,則不進(jìn)行注入if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Abstract annotation is not supported on static fields: " + field);}return;}currElements.add(new AbstractFieldElement(field, ann));}});//數(shù)據(jù)加到數(shù)組最前方 父類的的注解都放在靠前的位置elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);}@Nullableprivate MergedAnnotation<?> findAbstractAnnotation(AccessibleObject ao) {// 將指定方法上的注解合并成一個(gè)注解MergedAnnotations annotations = MergedAnnotations.from(ao);// 循環(huán)要掃描的注解 annotationTypes 那個(gè)在前面就認(rèn)哪個(gè)for (Class<? extends Annotation> type : this.annotationTypes) {MergedAnnotation<?> annotation = annotations.get(type);if (annotation.isPresent()) {return annotation;}}return null;}@Deprecated@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {return postProcessProperties(pvs, bean, beanName);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}/*** 實(shí)現(xiàn)交給子類進(jìn)行實(shí)現(xiàn) 將注解透?jìng)鞒鋈? @param mergedAnnotation 屬性上的注解* @param bean bean實(shí)例* @param beanName bean的名字* @param field 字段* @param autowiredFieldElement 注解* @return 注入對(duì)象* @throws Exception*/protected abstract Object getInjectedObject(MergedAnnotation<?> mergedAnnotation, Object bean, String beanName, Field field,AbstractFieldElement autowiredFieldElement) throws Exception;public class AbstractFieldElement extends InjectionMetadata.InjectedElement {private final MergedAnnotation<?> mergedAnnotation;public AbstractFieldElement(Field field, MergedAnnotation<?> mergedAnnotation) {super(field, null);this.mergedAnnotation = mergedAnnotation;}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Field field = (Field) this.member;Object value = getInjectedObject(this.mergedAnnotation, bean, beanName, field, this);if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}}}
  • 抽象類實(shí)現(xiàn),實(shí)現(xiàn)一個(gè)?@RedisAutowired?自定義注入注解
package com.yunlongn.common.core.autowired;import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.core.annotation.MergedAnnotation;import java.lang.annotation.Annotation; import java.lang.reflect.Field;public class RedisAutowiredBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements BeanFactoryAware {private BeanFactory beanFactory = null;@Overridepublic Class<? extends Annotation> annotationType() {return RedisAutowired.class;}@Overrideprotected Object getInjectedObject(MergedAnnotation<?> mergedAnnotation, Object bean, String beanName, Field field,AbstractAnnotationBeanPostProcessor.AbstractFieldElement autowiredFieldElement) throws Exception {// 從value中獲取bean的名字。 或者通過(guò)一些其他的邏輯獲取名字String s = mergedAnnotation.getString("value");return beanFactory.getBean(s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;} }
  • 在 Application 引入以上 @Import(RedisAutowiredBeanPostProcessor.class) 那么?@RedisAutowired?注解就生效了
@RedisAutowired("db102")private XXXService service;
  • 使用注解如上

總結(jié)

以上是生活随笔為你收集整理的从源码层面带你实现一个自动注入注解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。