spring security ObjectPostProcessor解析

頂層接口

  • org.springframework.security.config.annotation.ObjectPostProcessor
    SecurityBuilder 的抽象實(shí)現(xiàn)AbstractConfiguredSecurityBuilder中被引入。
    并且通過構(gòu)造函數(shù)入?yún)⒈辉O(shè)置并且構(gòu)造函數(shù)為protected只能被子類實(shí)例化根暑。
protected AbstractConfiguredSecurityBuilder(
            ObjectPostProcessor<Object> objectPostProcessor) {
        this(objectPostProcessor, false);
    }
protected AbstractConfiguredSecurityBuilder(
            ObjectPostProcessor<Object> objectPostProcessor,
            boolean allowConfigurersOfSameType) {
        Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null");
        this.objectPostProcessor = objectPostProcessor;
        this.allowConfigurersOfSameType = allowConfigurersOfSameType;
    }
  • ObjectPostProcessor
public interface ObjectPostProcessor<T> {

    //僅有一個(gè)方法用于初始化修改后的返回修改后的對(duì)象呀打,我們來看看它的具體實(shí)現(xiàn)
    <O extends T> O postProcess(O object);
}
  • AutowireBeanFactoryObjectPostProcessor
//此類被final修飾,無法繼承劣砍,并且此處實(shí)現(xiàn)了SmartInitializingSingleton該接口
//需實(shí)現(xiàn)afterSingletonsInstantiated,可以對(duì)bean初始化時(shí)做一些其它的事情扇救。
//并實(shí)現(xiàn)了DisposableBean刑枝,即銷毀時(shí)需要自己處理。
final class AutowireBeanFactoryObjectPostProcessor
        implements ObjectPostProcessor<Object>, DisposableBean, SmartInitializingSingleton {
    private final Log logger = LogFactory.getLog(getClass());
    //通過此接口擴(kuò)展使Spring框架之外的程序迅腔,具有自動(dòng)裝配的功能装畅。
    private final AutowireCapableBeanFactory autowireBeanFactory;
    private final List<DisposableBean> disposableBeans = new ArrayList<>();
    private final List<SmartInitializingSingleton> smartSingletons = new ArrayList<>();

    public AutowireBeanFactoryObjectPostProcessor(
            AutowireCapableBeanFactory autowireBeanFactory) {
        Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null");
        this.autowireBeanFactory = autowireBeanFactory;
    }
    //ObjectPostProcessor接口的方法實(shí)現(xiàn)。
    @SuppressWarnings("unchecked")
    public <T> T postProcess(T object) {
        if (object == null) {
            return null;
        }
        T result = null;
        try {
        //通過AutowireCapableBeanFactory 的初始化方法將對(duì)象交給spring 管理
            result = (T) this.autowireBeanFactory.initializeBean(object,
                    object.toString());
        }
        catch (RuntimeException e) {
            Class<?> type = object.getClass();
            throw new RuntimeException(
                    "Could not postProcess " + object + " of type " + type, e);
        }
        //通過調(diào)用給定Bean的after-instantiation及post-processing接口沧烈,對(duì)bean進(jìn)行配置
        this.autowireBeanFactory.autowireBean(object);
        //判斷當(dāng)前bean是否實(shí)現(xiàn)DisposableBean 接口如果實(shí)現(xiàn)就加入disposableBeans容器備用
        if (result instanceof DisposableBean) {
            this.disposableBeans.add((DisposableBean) result);
        }
        //同上
        if (result instanceof SmartInitializingSingleton) {
            this.smartSingletons.add((SmartInitializingSingleton) result);
        }
        return result;
    }

    //單例實(shí)例化之后處理掠兄,即傳入的對(duì)象需要實(shí)現(xiàn)afterSingletonsInstantiated接口
    //處理在postProcess階段存入smartSingletons的實(shí)例
    @Override
    public void afterSingletonsInstantiated() {
        for (SmartInitializingSingleton singleton : smartSingletons) {
            singleton.afterSingletonsInstantiated();
        }
    }

    //銷毀之前存入disposableBeans的需銷毀對(duì)象
    public void destroy() throws Exception {
        for (DisposableBean disposable : this.disposableBeans) {
            try {
                disposable.destroy();
            }
            catch (Exception error) {
                this.logger.error(error);
            }
        }
    }

}

以上對(duì)象使用@Bean方式配置,在ObjectPostProcessorConfiguration中注入了


@Configuration
public class ObjectPostProcessorConfiguration {

    @Bean
    public ObjectPostProcessor<Object> objectPostProcessor(
            AutowireCapableBeanFactory beanFactory) {
        return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
    }
}

ObjectPostProcessorConfiguration 在 AuthenticationConfiguration時(shí)被@Import進(jìn)來。

@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration

而 AuthenticationConfiguration則是通過@EnableGlobalAuthentication 注解導(dǎo)入蚂夕,這個(gè)注解又是被@EnableWebSecurity 注解導(dǎo)入迅诬。

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
        SpringWebMvcImportSelector.class,
        OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {

接著我們來看它的另一個(gè)實(shí)現(xiàn)CompositeObjectPostProcessor

private static final class CompositeObjectPostProcessor implements
            ObjectPostProcessor<Object> {
            //定義一個(gè)容器裝ObjectPostProcessor對(duì)象
        private List<ObjectPostProcessor<? extends Object>> postProcessors = new ArrayList<ObjectPostProcessor<?>>();

        @SuppressWarnings({ "rawtypes", "unchecked" })
        public Object postProcess(Object object) {
            for (ObjectPostProcessor opp : postProcessors) {
                Class<?> oppClass = opp.getClass();
                //泛型解析器
                Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,
                        ObjectPostProcessor.class);
                //判斷該泛型對(duì)象是否與傳入對(duì)象相對(duì)應(yīng)如果對(duì)應(yīng)則執(zhí)行該對(duì)象的postProcess方法
                if (oppType == null || oppType.isAssignableFrom(object.getClass())) {
                    object = opp.postProcess(object);
                }
            }
            return object;
        }

        //往容器中添加ObjectPostProcessor對(duì)象并根據(jù)Ordered注解進(jìn)行排序返回是否添加成功
        private boolean addObjectPostProcessor(
                ObjectPostProcessor<? extends Object> objectPostProcessor) {
            boolean result = this.postProcessors.add(objectPostProcessor);
            Collections.sort(postProcessors, AnnotationAwareOrderComparator.INSTANCE);
            return result;
        }
    }

CompositeObjectPostProcessor 是SecurityConfigurerAdapter 的一個(gè)靜態(tài)內(nèi)部類,僅用來返回對(duì)象使用婿牍,這邊是將原對(duì)象傳進(jìn)去侈贷,執(zhí)行對(duì)象的postProcess做一些修改之后在把對(duì)象返回回來。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末牍汹,一起剝皮案震驚了整個(gè)濱河市铐维,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慎菲,老刑警劉巖嫁蛇,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異露该,居然都是意外死亡睬棚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門解幼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抑党,“玉大人,你說我怎么就攤上這事撵摆〉卓浚” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵特铝,是天一觀的道長暑中。 經(jīng)常有香客問我,道長鲫剿,這世上最難降的妖魔是什么鳄逾? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮灵莲,結(jié)果婚禮上雕凹,老公的妹妹穿的比我還像新娘。我一直安慰自己政冻,他們只是感情好枚抵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赠幕,像睡著了一般俄精。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上榕堰,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼逆屡。 笑死圾旨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的魏蔗。 我是一名探鬼主播砍的,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼莺治!你這毒婦竟也來了廓鞠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤谣旁,失蹤者是張志新(化名)和其女友劉穎床佳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榄审,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砌们,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搁进。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浪感。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖饼问,靈堂內(nèi)的尸體忽然破棺而出影兽,到底是詐尸還是另有隱情,我是刑警寧澤莱革,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布峻堰,位于F島的核電站,受9級(jí)特大地震影響驮吱,放射性物質(zhì)發(fā)生泄漏茧妒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一左冬、第九天 我趴在偏房一處隱蔽的房頂上張望桐筏。 院中可真熱鬧,春花似錦拇砰、人聲如沸梅忌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牧氮。三九已至,卻和暖如春瑰枫,著一層夾襖步出監(jiān)牢的瞬間踱葛,已是汗流浹背丹莲。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尸诽,地道東北人甥材。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像性含,于是被迫代替她去往敵國和親洲赵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容