Spring Annotaion Support詳細(xì)介紹及簡(jiǎn)單實(shí)例
最近正在看spring官網(wǎng),看Spring IOC的時(shí)候看Spring容器擴(kuò)展點(diǎn)的時(shí)候發(fā)現(xiàn)了BeanPostProcessor 這個(gè)接口。下面是官方對(duì)它的詳細(xì)描述:
BeanPostProcessor接口定義了回調(diào)方法,您可以實(shí)現(xiàn)提供自己的(或覆蓋容器的默認(rèn))實(shí)例化邏輯,依賴(lài)性解析邏輯,等等。如果你想實(shí)現(xiàn)一些自定義邏輯Spring容器實(shí)例化完成后,配置和初始化一個(gè)bean,您可以插入一個(gè)或多個(gè)BeanPostProcessor實(shí)現(xiàn)。
您可以配置多個(gè)BeanPostProcessor實(shí)例,您可以控制的順序執(zhí)行這些BeanPostProcessors通過(guò)設(shè)置屬性。你可以設(shè)置這個(gè)屬性只有BeanPostProcessor實(shí)現(xiàn)命令接口;如果你寫(xiě)自己的BeanPostProcessor你也應(yīng)該考慮實(shí)現(xiàn)theOrdered接口。詳情,請(qǐng)咨詢(xún)BeanPostProcessor的Javadoc和命令接口。
BeanPostProcessor有兩個(gè)方法postProcessBeforeInitialization,postProcessAfterInitialization.如果一個(gè)對(duì)象實(shí)現(xiàn)了這個(gè)接口,那么就會(huì)在容器初始化init方法之前(就像InitializingBean的afterPropertiesSet()和其它公開(kāi)的init方法)或在Spring bean初始化之后執(zhí)行回調(diào)。
實(shí)現(xiàn)BeanPostProcessor接口的類(lèi)由容器是特殊而區(qū)別對(duì)待。所有BeanPostProcessors和他們?cè)趩?dòng)時(shí)直接引用實(shí)例化bean,作為特殊的ApplicationContext的啟動(dòng)階段。接下來(lái),所有BeanPostProcessorsare注冊(cè)分類(lèi)的方式,適用于所有進(jìn)一步bean容器。因?yàn)閷?shí)現(xiàn)AOP auto-proxying aBeanPostProcessor本身,無(wú)論是BeanPostProcessors還是beas他們有資格獲得auto-proxying直接引用,因此沒(méi)有方面編織進(jìn)去。
實(shí)現(xiàn)BeanPostProcessor接口的類(lèi)由容器是特殊而區(qū)別對(duì)待。所有BeanPostProcessors和他們?cè)趩?dòng)時(shí)直接引用實(shí)例化bean,作為特殊的ApplicationContext的啟動(dòng)階段。接下來(lái),所有BeanPostProcessorsare注冊(cè)分類(lèi)的方式,適用于所有進(jìn)一步bean容器。因?yàn)閷?shí)現(xiàn)AOP auto-proxying aBeanPostProcessor本身,無(wú)論是BeanPostProcessors還是beas他們有資格獲得auto-proxying直接引用,因此沒(méi)有方面編織進(jìn)去。
使用回調(diào)接口或注釋與自定義實(shí)現(xiàn)BeanPostProcessor是一種常見(jiàn)的擴(kuò)展SpringIoC容器。RequiredAnnotationBeanPostProcessor是Spring的一個(gè)例子 —— 一個(gè)實(shí)現(xiàn)BeanPostProcessor附帶的Spring分布,確保JavaBean屬性bean上標(biāo)有一個(gè)(任意)注釋(配置)會(huì)依賴(lài)注入值。
你說(shuō)我一看到上面的AOP這個(gè)Spring兩大特性之一我心里面都有一點(diǎn)小激動(dòng)。后面他再來(lái)個(gè)Spring的Annotation一般也是用這個(gè)接口實(shí)現(xiàn)的。這下就忍不住了想去看一看RequiredAnnotationBeanPostProcessor這個(gè)類(lèi)到底干了什么。直接上源碼
Spring Annotation Support /* * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.annotation; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.Conventions; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; /** * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation * that enforces required JavaBean properties to have been configured. * 強(qiáng)制檢測(cè)JavaBean必須的properties是否已經(jīng)被配置 * Required bean properties are detected through a Java 5 annotation: * 必須的bean屬性通過(guò)Java 5中的annotation自動(dòng)檢測(cè)到 * by default, Spring's {@link Required} annotation. * * <p>The motivation for the existence of this BeanPostProcessor is to allow * BeanPostProcessor存在的意義是允許 * developers to annotate the setter properties of their own classes with an * arbitrary JDK 1.5 annotation to indicate that the container must check * for the configuration of a dependency injected value. This neatly pushes * 開(kāi)發(fā)人員注釋setter屬性與一個(gè)他們自己的類(lèi)任意的JDK 1.5注釋表明容器必須檢查依賴(lài)注入的配置值。 * responsibility for such checking onto the container (where it arguably belongs), * 這樣就巧妙的把check的責(zé)任給了Spring容器(它應(yīng)該就屬于的) * and obviates the need (<b>in part</b>) for a developer to code a method that * simply checks that all required properties have actually been set. * 這樣也就排除了開(kāi)發(fā)人員需要編寫(xiě)一個(gè)簡(jiǎn)單的方法用來(lái)檢測(cè)那么必須的properties是否已經(jīng)設(shè)置了值 * <p>Please note that an 'init' method may still need to implemented (and may * still be desirable), because all that this class does is enforce that a * 請(qǐng)注意初始化方法還是必須要實(shí)現(xiàn)的(并且仍然是可取的) * 'required' property has actually been configured with a value. It does * 因?yàn)樗羞@個(gè)Class強(qiáng)制執(zhí)行的是'required'屬性是否已經(jīng)被配置了值 * <b>not</b> check anything else... In particular, it does not check that a * 它并不會(huì)check其實(shí)的事,特別的是,它不會(huì)check這個(gè)配置的值是不是null值 * configured value is not {@code null}. * * <p>Note: A default RequiredAnnotationBeanPostProcessor will be registered * by the "context:annotation-config" and "context:component-scan" XML tags. * 當(dāng)你使用了"context:annotation-config"或者"context:component-scan"XML標(biāo)簽就會(huì)默認(rèn)注冊(cè)RequiredAnnotationBeanPostProcessor * Remove or turn off the default annotation configuration there if you intend * to specify a custom RequiredAnnotationBeanPostProcessor bean definition. * 你如果打算指定一個(gè)自定義的RequiredAnnotationBeanPostProcessor的bean實(shí)現(xiàn)可以移除或者關(guān)閉默認(rèn)的annotation配置 * * @author Rob Harrop * @author Juergen Hoeller * @since 2.0 * @see #setRequiredAnnotationType * @see Required */ public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { /** * Bean definition attribute that may indicate whether a given bean is supposed * to be skipped when performing this post-processor's required property check. * 這個(gè)bean定義的屬性表明當(dāng)執(zhí)行post-processor(后處理程序)這個(gè)check提供的bean的必須的屬性 * @see #shouldSkip */ public static final String SKIP_REQUIRED_CHECK_ATTRIBUTE = Conventions.getQualifiedAttributeName(RequiredAnnotationBeanPostProcessor.class, "skipRequiredCheck"); private Class<? extends Annotation> requiredAnnotationType = Required.class; private int order = Ordered.LOWEST_PRECEDENCE - 1; private ConfigurableListableBeanFactory beanFactory; /** * Cache for validated bean names, skipping re-validation for the same bean * 緩存已經(jīng)確認(rèn)過(guò)的bean名稱(chēng),跳過(guò)后續(xù)同樣的bean */ private final Set<String> validatedBeanNames = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64)); /** * Set the 'required' annotation type, to be used on bean property * setter methods. * 設(shè)置所需的注釋類(lèi)型,使用bean屬性setter方法 * <p>The default required annotation type is the Spring-provided * {@link Required} annotation. * 這個(gè)默認(rèn)的required annotation類(lèi)型是Spring提供的annotation * <p>This setter property exists so that developers can provide their own * (non-Spring-specific) annotation type to indicate that a property value * is required. * 這里設(shè)置這個(gè)property是為了開(kāi)發(fā)者能夠提供自己定義的annotaion類(lèi)型用來(lái)表明這個(gè)屬性值是必須的 */ public void setRequiredAnnotationType(Class<? extends Annotation> requiredAnnotationType) { Assert.notNull(requiredAnnotationType, "'requiredAnnotationType' must not be null"); this.requiredAnnotationType = requiredAnnotationType; } /** * Return the 'required' annotation type. */ protected Class<? extends Annotation> getRequiredAnnotationType() { return this.requiredAnnotationType; } @Override public void setBeanFactory(BeanFactory beanFactory) { if (beanFactory instanceof ConfigurableListableBeanFactory) { this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } } public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { } @Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { // 利用緩存確定是否這個(gè)bean被validated if (!this.validatedBeanNames.contains(beanName)) { // 不跳過(guò) if (!shouldSkip(this.beanFactory, beanName)) { List<String> invalidProperties = new ArrayList<String>(); for (PropertyDescriptor pd : pds) { // 如果被標(biāo)記為了required 且 這個(gè)屬性沒(méi)有屬性值(或其他處理?xiàng)l目) if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) { // 增加這個(gè)屬性 invalidProperties.add(pd.getName()); } } // <span style="color:#ff0000;">如果無(wú)效的properties不為空。拋出異常</span> if (!invalidProperties.isEmpty()) { throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName)); } } // 把需要驗(yàn)證的bean名稱(chēng)添加進(jìn)去 this.validatedBeanNames.add(beanName); } return pvs; } /** * Check whether the given bean definition is not subject to the annotation-based * required property check as performed by this post-processor. * 通過(guò)post-processor(后處理程序)檢測(cè)這個(gè)被給予的定義的bean是否受注釋為基礎(chǔ)的check必須的property的管束 * <p>The default implementations check for the presence of the * {@link #SKIP_REQUIRED_CHECK_ATTRIBUTE} attribute in the bean definition, if any. * 這個(gè)默認(rèn)的實(shí)現(xiàn)check存在SKIP_REQUIRED_CHECK_ATTRIBUTE這個(gè)屬性的定義的bean * It also suggests skipping in case of a bean definition with a "factory-bean" * reference set, assuming that instance-based factories pre-populate the bean. * 它同樣也建議跳過(guò)如果這個(gè)bean定義了"factory-bean"引用,假設(shè)那個(gè)基于實(shí)例的factories預(yù)先配置了bean * @param beanFactory the BeanFactory to check against * @param beanName the name of the bean to check against * @return {@code true} to skip the bean; {@code false} to process it * 如果返回 true跳過(guò)這個(gè)bean,返回false就處理它 */ protected boolean shouldSkip(ConfigurableListableBeanFactory beanFactory, String beanName) { // 如果這個(gè)beanFacotry為空或者這個(gè)bean工廠不包含一個(gè)給定名稱(chēng)的bean定義。返回false if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) { return false; } BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); // 判斷這個(gè)bean的工廠beanName,如果不為null,返回true if (beanDefinition.getFactoryBeanName() != null) { return true; } Object value = beanDefinition.getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE); return (value != null && (Boolean.TRUE.equals(value) || Boolean.valueOf(value.toString()))); } /** * Is the supplied property required to have a value (that is, to be dependency-injected)? * 是否這個(gè)提供的必須的propery是否有一個(gè)值(這個(gè)是被依賴(lài)注入)? * <p>This implementation looks for the existence of a * {@link #setRequiredAnnotationType "required" annotation} * on the supplied {@link PropertyDescriptor property}. * 這個(gè)實(shí)現(xiàn)是為了找到提供的ProertyDescriptor是提供了"required"注解 * @param propertyDescriptor the target PropertyDescriptor (never {@code null}) * @return {@code true} if the supplied property has been marked as being required; * 返回true,如果提供的property已經(jīng)被標(biāo)記為必須的</span> * {@code false} if not, or if the supplied property does not have a setter method * 返回false,如果沒(méi)有標(biāo)記為必須的或者提供的property沒(méi)有一個(gè)setter方法 */ protected boolean isRequiredProperty(PropertyDescriptor propertyDescriptor) { Method setter = propertyDescriptor.getWriteMethod(); return (setter != null && AnnotationUtils.getAnnotation(setter, getRequiredAnnotationType()) != null); } /** * Build an exception message for the given list of invalid properties. * 使用所給的異常properties來(lái)構(gòu)建異常信息 * @param invalidProperties the list of names of invalid properties * @param beanName the name of the bean * @return the exception message */ private String buildExceptionMessage(List<String> invalidProperties, String beanName) { int size = invalidProperties.size(); StringBuilder sb = new StringBuilder(); sb.append(size == 1 ? "Property" : "Properties"); for (int i = 0; i < size; i++) { String propertyName = invalidProperties.get(i); if (i > 0) { if (i == (size - 1)) { sb.append(" and"); } else { sb.append(","); } } sb.append(" '").append(propertyName).append("'"); } sb.append(size == 1 ? " is" : " are"); sb.append(" required for bean '").append(beanName).append("'"); return sb.toString(); } }
在上面的代碼中所示。我們可以得出以下結(jié)論:
上面已經(jīng)把Spring對(duì)于 org.springframework.beans.factory.annotation.Required 這個(gè)標(biāo)簽的實(shí)現(xiàn)出來(lái)了。雖然只是一個(gè)小例子。但是我們可以根據(jù)Spring以下的的包結(jié)構(gòu)看到這是Spring對(duì)于它自身Annotation的很common的實(shí)現(xiàn):
從上面的例子中我可以看出Spring對(duì)它本身的Annotaion的一種實(shí)現(xiàn)。當(dāng)前文中并沒(méi)有講述Exception Message是通過(guò)怎么傳遞的。但是這并不是本文討論的范疇,有興趣的朋友可以自己去看看。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
詳解JSP中使用過(guò)濾器進(jìn)行內(nèi)容編碼的解決辦法
這篇文章主要介紹了詳解JSP中使用過(guò)濾器進(jìn)行內(nèi)容編碼的解決辦法的相關(guān)資料,希望通過(guò)本文能幫助到大家,理解正確使用過(guò)濾器編碼的問(wèn)題,需要的朋友可以參考下2017-09-09ResourceBundle類(lèi)在jsp中的國(guó)際化實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇ResourceBundle類(lèi)在jsp中的國(guó)際化實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07用jsp頁(yè)面生成隨機(jī)的驗(yàn)證數(shù)字碼示例
生成隨機(jī)的驗(yàn)證數(shù)字碼有很多種方法,下面為大家將介紹下如何用jsp頁(yè)面生成隨機(jī)的驗(yàn)證碼,感興趣的朋友可以參考下2013-09-09JSP 自定義標(biāo)簽之一 簡(jiǎn)單實(shí)例
當(dāng)前軟件開(kāi)發(fā)越來(lái)越重視分工與協(xié)作,對(duì)于JSP技術(shù)而言,視圖層與模型層分別由不同的團(tuán)隊(duì)完成也成為理所當(dāng)然的選擇,基于技術(shù)專(zhuān)長(zhǎng)不同及其它因素考慮,眾多規(guī)范中都明確要求JSP頁(yè)面代碼中不允許出現(xiàn)Java代碼。2009-07-07JSP中js傳遞和解析URL參數(shù)以及中文轉(zhuǎn)碼和解碼問(wèn)題
有關(guān)js傳遞和解析URL參數(shù)以及中文轉(zhuǎn)碼和解碼問(wèn)題,都是在js中很常見(jiàn)的,下面通過(guò)示例簡(jiǎn)單為大家介紹下,感興趣的朋友可以參考下2013-10-10在jsp中用bean和servlet聯(lián)合實(shí)現(xiàn)用戶(hù)注冊(cè)、登錄
在jsp中用bean和servlet聯(lián)合實(shí)現(xiàn)用戶(hù)注冊(cè)、登錄...2006-10-10純jsp實(shí)現(xiàn)的倒計(jì)時(shí)動(dòng)態(tài)顯示效果完整代碼
這篇文章主要介紹了純jsp實(shí)現(xiàn)的倒計(jì)時(shí)動(dòng)態(tài)顯示效果代碼,涉及JSP時(shí)間操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10