本文是一个 spring 扩展支持 spel 的简单模式,方便第三方通过 spring 提供额外功能。
简化版方式
这种方式可以在任何能获取applicationcontext
的地方使用。还可以提取一个方法处理动态 spel 表达式。
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;
/**
* 针对 spring 实现某些特殊逻辑时,支持 spel 表达式
* @author liuzh
*/
public class spelutil implements applicationcontextaware {
/**
* 通过 applicationcontext 处理时
* @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 );
//根据自己逻辑处理
//例如获取 bean
object bean = applicationcontext.getbean(definitionname);
//获取实际类型
class <?> targetclass = aoputils.gettargetclass(bean);
//获取所有方法
for (method method : targetclass.getdeclaredmethods()) {
//获取自定义的注解(bean是个例子)
bean annotation = annotationutils.findannotation(method, bean. class );
//假设下面的 value 支持 spel
for (string val : annotation.value()) {
//解析 ${} 方式的值
val = beanfactory.resolveembeddedvalue(val);
//解析 spel 表达式
object value = expressionresolver.evaluate(val, new beanexpressioncontext(beanfactory, scope));
//todo 其他逻辑
}
}
}
}
}
}
|
上面是完全针对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;
/**
* 针对 spring 实现某些特殊逻辑时,支持 spel 表达式
* @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;
}
/**
* 对 bean 的后置处理
* @param bean
* @param beanname
* @return
* @throws beansexception
*/
@override
public object postprocessafterinitialization(object bean, string beanname) throws beansexception {
//获取实际类型
class <?> targetclass = aoputils.gettargetclass(bean);
//获取所有方法
reflectionutils.dowithmethods(targetclass, method -> {
//获取自定义的注解(bean是个例子)
bean annotation = annotationutils.findannotation(method, bean. class );
//假设下面的 value 支持 spel
for (string val : annotation.value()) {
//解析表达式
object value = resolveexpression(val);
//todo 其他逻辑
}
}, method -> {
//todo 过滤方法
return true ;
});
return null ;
}
}
|
这种方式利用了 spring 生命周期的几个接口来获取需要用到的对象。
spring 生命周期调用顺序
扩展 spring 我们必须了解这个顺序,否则就没法正确的使用各中对象。
完整的初始化方法及其标准顺序是:
- beannameaware 的 setbeanname 方法
- beanclassloaderaware 的 setbeanclassloader 方法
- beanfactoryaware 的 setbeanfactory 方法
- environmentaware 的 setenvironment 方法
- embeddedvalueresolveraware 的 setembeddedvalueresolver 方法
- resourceloaderaware 的 setresourceloader 方法 (仅在应用程序上下文中运行时适用)
- applicationeventpublisheraware 的 setapplicationeventpublisher 方法 (仅在应用程序上下文中运行时适用)
- messagesourceaware 的 setmessagesource 方法 (仅在应用程序上下文中运行时适用)
- applicationcontextaware 的 setapplicationcontext 方法 (仅在应用程序上下文中运行时适用)
- servletcontextaware 的 setservletcontext 方法 (仅在web应用程序上下文中运行时适用)
- beanpostprocessors 的 postprocessbeforeinitialization 方法
- initializingbean 的 afterpropertiesset 方法
- 自定义初始化方法
- beanpostprocessors 的 postprocessafterinitialization 方法
关闭bean工厂时,以下生命周期方法适用:
- destructionawarebeanpostprocessors 的 postprocessbeforedestruction 方法
- disposablebean 的 destroy 方法
- 自定义销毁方法
灵活运用
利用上述模式可以实现很多便捷的操作。
spring 中,使用类似模式的地方有:
- @value 注解支持 spel(和 ${})
- @cache 相关的注解(支持 spel)
- @eventlistener 注解
- @rabbitlistener 注解
- …
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。如果你想了解更多相关内容请查看下面相关链接
原文链接:https://blog.csdn.net/isea533/article/details/84100428