本文是一個(gè) spring 擴(kuò)展支持 spel 的簡(jiǎn)單模式,方便第三方通過 spring 提供額外功能。
簡(jiǎn)化版方式
這種方式可以在任何能獲取applicationcontext
的地方使用。還可以提取一個(gè)方法處理動(dòng)態(tài) spel 表達(dá)式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import org.springframework.aop.support.aoputils; import org.springframework.beans.beansexception; import org.springframework.beans.factory.config.*; import org.springframework.context.applicationcontext; import org.springframework.context.applicationcontextaware; import org.springframework.context.configurableapplicationcontext; import org.springframework.context.annotation.bean; import org.springframework.context.expression.standardbeanexpressionresolver; import org.springframework.core.annotation.annotationutils; import java.lang.reflect.method; /** * 針對(duì) spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 spel 表達(dá)式 * @author liuzh */ public class spelutil implements applicationcontextaware { /** * 通過 applicationcontext 處理時(shí) * @param applicationcontext * @throws beansexception */ @override public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception { if (applicationcontext instanceof configurableapplicationcontext) { configurableapplicationcontext context = (configurableapplicationcontext)applicationcontext; configurablelistablebeanfactory beanfactory = context.getbeanfactory(); standardbeanexpressionresolver expressionresolver = new standardbeanexpressionresolver(beanfactory.getbeanclassloader()); for (string definitionname : applicationcontext.getbeandefinitionnames()) { beandefinition definition = beanfactory.getbeandefinition(definitionname); scope scope = (definition != null ? beanfactory.getregisteredscope(definition.getscope()) : null ); //根據(jù)自己邏輯處理 //例如獲取 bean object bean = applicationcontext.getbean(definitionname); //獲取實(shí)際類型 class <?> targetclass = aoputils.gettargetclass(bean); //獲取所有方法 for (method method : targetclass.getdeclaredmethods()) { //獲取自定義的注解(bean是個(gè)例子) bean annotation = annotationutils.findannotation(method, bean. class ); //假設(shè)下面的 value 支持 spel for (string val : annotation.value()) { //解析 ${} 方式的值 val = beanfactory.resolveembeddedvalue(val); //解析 spel 表達(dá)式 object value = expressionresolver.evaluate(val, new beanexpressioncontext(beanfactory, scope)); //todo 其他邏輯 } } } } } } |
上面是完全針對(duì)applicationcontext
的,下面是更推薦的一種用法。
推薦方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
import org.springframework.aop.support.aoputils; import org.springframework.beans.beansexception; import org.springframework.beans.factory.beanclassloaderaware; import org.springframework.beans.factory.beanfactory; import org.springframework.beans.factory.beanfactoryaware; import org.springframework.beans.factory.config.*; import org.springframework.context.annotation.bean; import org.springframework.context.expression.standardbeanexpressionresolver; import org.springframework.core.annotation.annotationutils; import org.springframework.util.reflectionutils; /** * 針對(duì) spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 spel 表達(dá)式 * @author liuzh */ public class spelutil2 implements beanpostprocessor, beanfactoryaware, beanclassloaderaware { private beanfactory beanfactory; private beanexpressionresolver resolver; private beanexpressioncontext expressioncontext; /** * 解析 spel * @param value * @return */ private object resolveexpression(string value){ string resolvedvalue = resolve(value); if (!(resolvedvalue.startswith( "#{" ) && value.endswith( "}" ))) { return resolvedvalue; } return this .resolver.evaluate(resolvedvalue, this .expressioncontext); } /** * 解析 ${} * @param value * @return */ private string resolve(string value){ if ( this .beanfactory != null && this .beanfactory instanceof configurablebeanfactory) { return ((configurablebeanfactory) this .beanfactory).resolveembeddedvalue(value); } return value; } @override public void setbeanclassloader(classloader classloader) { this .resolver = new standardbeanexpressionresolver(classloader); } @override public void setbeanfactory(beanfactory beanfactory) throws beansexception { this .beanfactory = beanfactory; if (beanfactory instanceof configurablelistablebeanfactory){ this .resolver = ((configurablelistablebeanfactory) beanfactory).getbeanexpressionresolver(); this .expressioncontext = new beanexpressioncontext((configurablelistablebeanfactory) beanfactory, null ); } } @override public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception { return bean; } /** * 對(duì) bean 的后置處理 * @param bean * @param beanname * @return * @throws beansexception */ @override public object postprocessafterinitialization(object bean, string beanname) throws beansexception { //獲取實(shí)際類型 class <?> targetclass = aoputils.gettargetclass(bean); //獲取所有方法 reflectionutils.dowithmethods(targetclass, method -> { //獲取自定義的注解(bean是個(gè)例子) bean annotation = annotationutils.findannotation(method, bean. class ); //假設(shè)下面的 value 支持 spel for (string val : annotation.value()) { //解析表達(dá)式 object value = resolveexpression(val); //todo 其他邏輯 } }, method -> { //todo 過濾方法 return true ; }); return null ; } } |
這種方式利用了 spring 生命周期的幾個(gè)接口來獲取需要用到的對(duì)象。
spring 生命周期調(diào)用順序
擴(kuò)展 spring 我們必須了解這個(gè)順序,否則就沒法正確的使用各中對(duì)象。
完整的初始化方法及其標(biāo)準(zhǔn)順序是:
- beannameaware 的 setbeanname 方法
- beanclassloaderaware 的 setbeanclassloader 方法
- beanfactoryaware 的 setbeanfactory 方法
- environmentaware 的 setenvironment 方法
- embeddedvalueresolveraware 的 setembeddedvalueresolver 方法
- resourceloaderaware 的 setresourceloader 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
- applicationeventpublisheraware 的 setapplicationeventpublisher 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
- messagesourceaware 的 setmessagesource 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
- applicationcontextaware 的 setapplicationcontext 方法 (僅在應(yīng)用程序上下文中運(yùn)行時(shí)適用)
- servletcontextaware 的 setservletcontext 方法 (僅在web應(yīng)用程序上下文中運(yùn)行時(shí)適用)
- beanpostprocessors 的 postprocessbeforeinitialization 方法
- initializingbean 的 afterpropertiesset 方法
- 自定義初始化方法
- beanpostprocessors 的 postprocessafterinitialization 方法
關(guān)閉bean工廠時(shí),以下生命周期方法適用:
- destructionawarebeanpostprocessors 的 postprocessbeforedestruction 方法
- disposablebean 的 destroy 方法
- 自定義銷毀方法
靈活運(yùn)用
利用上述模式可以實(shí)現(xiàn)很多便捷的操作。
spring 中,使用類似模式的地方有:
- @value 注解支持 spel(和 ${})
- @cache 相關(guān)的注解(支持 spel)
- @eventlistener 注解
- @rabbitlistener 注解
- …
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
原文鏈接:https://blog.csdn.net/isea533/article/details/84100428