- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring对静态变量无法注入的解决方案由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
今天在学习的过程中想写一个连接和线程绑定的JDBCUtils工具类,但测试时发现一直报空指针异常,上网查了之后Spring并不支持对静态成员变量注入,所以光试用@Autowired肯定是不行的.
可是我们编写工具类时肯定是要使用静态变量和方法的,我总结一下我用过可以实现对静态成员变量注入的方法.
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
|
@Component
public
class
JDBCUtils {
@Autowired
private
static
ComboPooledDataSource dataSource;
private
static
ThreadLocal<Connection> tl =
new
ThreadLocal<Connection>();
public
static
Connection getThreadConnection(){
Connection conn = tl.get();
if
(conn ==
null
){
conn = getConnection();
tl.set(conn);
}
return
conn;
}
public
static
DataSource getDataSource(){
return
dataSource;
}
public
static
Connection getConnection(){
Connection connection =
null
;
try
{
connection = dataSource.getConnection();
}
catch
(SQLException e) {
e.printStackTrace();
}
return
connection;
}
public
static
void
removeThreadConnection(){
tl.remove();
}
}
|
在类前加@Component注解,在set方法上加 @Autowired注解,这里注意两点 。
1.配置文件里已经配置了变量的相关参数 。
2.静态变量自动生成set方法时会有static修饰,要去掉,否则还是无法注入 。
1
2
3
4
5
6
7
|
@Component
public
class
JDBCUtils {
private
static
ComboPooledDataSource dataSource;
@Autowired
public
void
setDataSource(ComboPooledDataSource dataSource) {
JDBCUtils.dataSource = dataSource;
}
|
同样注意将set方法上的static去掉 。
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
|
public
class
JDBCUtils {
private
static
ComboPooledDataSource dataSource;
public
void
setDataSource(ComboPooledDataSource dataSource) {
this
.dataSource = dataSource;
}
private
static
ThreadLocal<Connection> tl =
new
ThreadLocal<Connection>();
public
static
Connection getThreadConnection(){
Connection conn = tl.get();
if
(conn ==
null
){
conn = getConnection();
tl.set(conn);
}
return
conn;
}
public
static
DataSource getDataSource(){
return
dataSource;
}
public
static
Connection getConnection(){
Connection connection =
null
;
try
{
connection = dataSource.getConnection();
}
catch
(SQLException e) {
e.printStackTrace();
}
return
connection;
}
public
static
void
removeThreadConnection(){
tl.remove();
}
}
|
1
2
3
|
<
bean
id
=
"JDBCUtils"
class
=
"com.cc.utils.JDBCUtils"
>
<
property
name
=
"dataSource"
ref
=
"dataSource"
></
property
>
</
bean
>
|
用@PostConstruct加在init方法上,在类初始化后执行该方法,对成员变量赋值。在这之前,我们要改造一下工具类,去掉我们想注入变量的static的修饰符,这样我们就可以用@Autowired实现对其注入.
然后加一个静态的类自身的引用对象,当我们想要变量时通过这个引用对象来获取.
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
|
@Component
public
class
JDBCUtils {
@Autowired
private
ComboPooledDataSource dataSource;
private
static
JDBCUtils jdbcUtils;
@PostConstruct
public
void
init(){
jdbcUtils =
this
;
this
.dataSource = dataSource;
}
private
static
ThreadLocal<Connection> tl =
new
ThreadLocal<Connection>();
public
static
Connection getThreadConnection(){
Connection conn = tl.get();
if
(conn ==
null
){
conn = getConnection();
tl.set(conn);
}
return
conn;
}
public
static
DataSource getDataSource(){
return
jdbcUtils.dataSource;
}
public
static
Connection getConnection(){
Connection connection =
null
;
try
{
connection = jdbcUtils.dataSource.getConnection();
}
catch
(SQLException e) {
e.printStackTrace();
}
return
connection;
}
public
static
void
removeThreadConnection(){
tl.remove();
}
}
|
当然这种用初始化方法也可以用xml配置,原理一样.
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
|
public
class
JDBCUtils {
private
ComboPooledDataSource dataSource;
public
void
setDataSource(ComboPooledDataSource dataSource) {
this
.dataSource = dataSource;
}
private
static
JDBCUtils jdbcUtils;
public
void
init(){
jdbcUtils =
this
;
this
.dataSource = dataSource;
}
private
static
ThreadLocal<Connection> tl =
new
ThreadLocal<Connection>();
public
static
Connection getThreadConnection(){
Connection conn = tl.get();
if
(conn ==
null
){
conn = getConnection();
tl.set(conn);
}
return
conn;
}
public
static
DataSource getDataSource(){
return
jdbcUtils.dataSource;
}
public
static
Connection getConnection(){
Connection connection =
null
;
try
{
connection = jdbcUtils.dataSource.getConnection();
}
catch
(SQLException e) {
e.printStackTrace();
}
return
connection;
}
public
static
void
removeThreadConnection(){
tl.remove();
}
}
|
1
2
3
|
<
bean
id
=
"JDBCUtils"
class
=
"com.cc.utils.JDBCUtils"
init-method
=
"init"
>
<
property
name
=
"dataSource"
ref
=
"dataSource"
></
property
>
</
bean
>
|
今天在写redission 的一个工具类的时候,随手写出下面的代码 。
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
|
package
com.wt.redission.wtredission.utils;
import
org.redisson.api.*;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Component;
import
javax.annotation.PostConstruct;
@Component
public
class
RedissionUtilserror {
@Autowired
private
static
RedissonClient redissonClient;
public
static
RLock getRLock(String objectName) {
RLock rLock =redissonClient.getLock(objectName);
return
rLock;
}
//根据名字获取map
public
static
<K, V> RMap<K, V> getRMap(String objectName) {
RMap<K, V> map = redissonClient.getMap(objectName);
return
map;
}
//根据名字和值设置map
public
static
void
setMap(String objectName,Object key,Object value){
RMap<Object, Object> map =redissonClient.getMap(objectName);
map.put(key,value);
}
//根据名字获取set
public
static
<V> RSet<V> getSet(String objectName) {
RSet<V> set = redissonClient.getSet(objectName);
return
set;
}
//根据名字和值设置set
public
static
void
setSet(String objectName,Object value){
RSet<Object> set = redissonClient.getSet(objectName);
set.add(value);
}
//根据名字获取list
public
static
<V> RList<V> getRList(String objectName) {
RList<V> rList = redissonClient.getList(objectName);
return
rList;
}
//根据名字和值设置list
public
static
void
setList(String objectName,
int
index,Object element ){
RList<Object> objectRList = redissonClient.getList(objectName);
objectRList.set(index,element);
}
//根据名字获取bucket
public
static
<T> RBucket<T> getRBucket(String objectName) {
RBucket<T> bucket = redissonClient.getBucket(objectName);
return
bucket;
}
//根据名字和值 设置对应的bucket
public
static
<T> T setBucket(String objectName,String value){
RBucket<Object> bucket = redissonClient.getBucket(objectName);
bucket.set(value);
T t= (T) bucket.get();
//值类型由返回值确定
return
t;
}
}
|
乍一看好像没问题 我写一个静态方法 然后在方法中使用静态变量redissonClient ,哇....,一切看得如此正常 。
当我开始测试时,NPE.............,我去这是怎么回事,自己在想这不科学啊,怎么会空指针,于是我开始找原因 。
最后发现是基础不牢啊............,对jvm的类加载机制几乎就没考虑,简要说要错误的原因 。
jvm在进行类加载的时候,首先会加载类变量,类方法,也就是我这里被static修饰的方法,然后当我调用静态方法进行使用的时候,会使用到redissionClient,注意这个redissionClient是通过autowired进来的,关键问题就在这里,autowired的底层是通过构造器和set方法注入bean的 。
redissionClient被static修饰 并且还是一个接口 在被调用的时候肯定没有实例化 。
下面提供三种方式正确使用 。
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
|
package
com.wt.redission.wtredission.utils;
import
org.redisson.api.*;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Component;
import
java.util.List;
@Component
public
class
RedissionUtils {
private
static
RedissonClient redissonClient;
@Autowired
public
RedissionUtils(RedissonClient redissonClient){
RedissionUtils.redissonClient=redissonClient;
}
public
static
RLock getRLock(String objectName) {
RLock rLock = redissonClient.getLock(objectName);
return
rLock;
}
//根据名字获取map
public
static
<K, V> RMap<K, V> getRMap(String objectName) {
RMap<K, V> map = redissonClient.getMap(objectName);
return
map;
}
//根据名字和值设置map
public
static
void
setMap(String objectName,Object key,Object value){
RMap<Object, Object> map =redissonClient.getMap(objectName);
map.put(key,value);
}
//根据名字获取set
public
static
<V> RSet<V> getSet(String objectName) {
RSet<V> set = redissonClient.getSet(objectName);
return
set;
}
//根据名字和值设置set
public
static
void
setSet(String objectName,Object value){
RSet<Object> set = redissonClient.getSet(objectName);
set.add(value);
}
//根据名字获取list
public
static
<V> RList<V> getRList(String objectName) {
RList<V> rList = redissonClient.getList(objectName);
return
rList;
}
//根据名字和值设置list
public
static
void
setList(String objectName,
int
index,Object element ){
RList<Object> objectRList = redissonClient.getList(objectName);
objectRList.set(index,element);
}
//根据名字获取bucket
public
static
<T> RBucket<T> getRBucket(String objectName) {
RBucket<T> bucket = redissonClient.getBucket(objectName);
return
bucket;
}
//根据名字和值 设置对应的bucket
public
static
<T> T setBucket(String objectName,String value){
RBucket<Object> bucket = redissonClient.getBucket(objectName);
bucket.set(value);
T t= (T) bucket.get();
//值类型由返回值确定
return
t;
}
}
|
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
|
package
com.wt.redission.wtredission.utils;
import
org.redisson.api.*;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Component;
import
javax.annotation.PostConstruct;
@Component
public
class
RedissionUtils2 {
@Autowired
RedissonClient redissonClient;
public
static
RedissionUtils2 redissionUtils;
@PostConstruct
public
void
init(){
redissionUtils=
this
;
redissionUtils.redissonClient=
this
.redissonClient;
}
public
static
RLock getRLock(String objectName) {
RLock rLock = redissionUtils.redissonClient.getLock(objectName);
return
rLock;
}
//根据名字获取map
public
static
<K, V> RMap<K, V> getRMap(String objectName) {
RMap<K, V> map = redissionUtils.redissonClient.getMap(objectName);
return
map;
}
//根据名字和值设置map
public
static
void
setMap(String objectName,Object key,Object value){
RMap<Object, Object> map =redissionUtils.redissonClient.getMap(objectName);
map.put(key,value);
}
//根据名字获取set
public
static
<V> RSet<V> getSet(String objectName) {
RSet<V> set = redissionUtils.redissonClient.getSet(objectName);
return
set;
}
//根据名字和值设置set
public
static
void
setSet(String objectName,Object value){
RSet<Object> set = redissionUtils.redissonClient.getSet(objectName);
set.add(value);
}
//根据名字获取list
public
static
<V> RList<V> getRList(String objectName) {
RList<V> rList = redissionUtils.redissonClient.getList(objectName);
return
rList;
}
//根据名字和值设置list
public
static
void
setList(String objectName,
int
index,Object element ){
RList<Object> objectRList = redissionUtils.redissonClient.getList(objectName);
objectRList.set(index,element);
}
//根据名字获取bucket
public
static
<T> RBucket<T> getRBucket(String objectName) {
RBucket<T> bucket = redissionUtils.redissonClient.getBucket(objectName);
return
bucket;
}
//根据名字和值 设置对应的bucket
public
static
<T> T setBucket(String objectName,String value){
RBucket<Object> bucket = redissionUtils.redissonClient.getBucket(objectName);
bucket.set(value);
T t= (T) bucket.get();
//值类型由返回值确定
return
t;
}
}
|
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
package
com.wt.redission.wtredission.utils;
import
io.micrometer.core.instrument.util.StringUtils;
import
org.springframework.beans.BeansException;
import
org.springframework.beans.factory.NoSuchBeanDefinitionException;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.ApplicationContextAware;
import
org.springframework.context.annotation.Scope;
import
org.springframework.stereotype.Component;
import
javax.servlet.http.HttpServletRequest;
/**
* Spring Context工具类.
*
* @author:Hohn
*/
@Component
@Scope
(
"singleton"
)
public
class
SpringUtil
implements
ApplicationContextAware {
/**
* Spring应用上下文环境.
*/
private
static
ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
*
* <br>
|
最后此篇关于Spring对静态变量无法注入的解决方案的文章就讲到这里了,如果你想了解更多关于Spring对静态变量无法注入的解决方案的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How to nest OR statements in JavaScript? 有没有办法做到这一点:
在 JavaScript 中有没有办法让一个变量总是等于一个变量?喜欢var1 = var2但是当var2更新,也是var1 . 例子 var var1 = document.getElementBy
我正在努力理解这代表什么 var1 = var2 == var3 我的猜测是这等同于: if (var2 == var3): var1 = var2 最佳答案 赋值 var1 = var2
这个问题已经有答案了: What does the PHP error message "Notice: Use of undefined constant" mean? (2 个回答) 已关闭 8
我在临时表中有几条记录,我想从每条记录中获取一个值并将其添加到一个变量中,例如 color | caption -------------------------------- re
如何将字符串转为变量(字符串变量--> $variable)? 或者用逗号分隔的变量列表然后转换为实际变量。 我有 2 个文件: 列名文件 行文件 我需要根据字符串匹配行文件中的整行,并根据列名文件命
我有一个我无法解决的基本 php 问题,我也想了解为什么! $upperValueCB = 10; $passNodeMatrixSource = 'CB'; $topValue= '$uppe
这可能吗? php $variable = $variable1 || $variable2? 如果 $variable1 为空则使用 $variable2 是否存在类似的东西? 最佳答案 PHP 5
在 Perl 5.20 中,for 循环似乎能够修改模块作用域的变量,但不能修改父作用域中的词法变量。 #!/usr/bin/env perl use strict; use warnings; ou
为什么这不起作用: var variable; variable = variable.concat(variable2); $('#lunk').append(variable) 我无法弄清楚这一点
根据我的理解,在32位机器上,指针的sizeof是32位(4字节),而在64位机器上,它是8字节。无论它们指向什么数据类型,它们都有固定的大小。我的计算机在 64 位上运行,但是当我打印包含 * 的大
例如: int a = 10; a += 1.5; 这运行得很完美,但是 a = a+1.5; 此作业表示类型不匹配:无法从 double 转换为 int。所以我的问题是:+= 运算符 和= 运算符
您好,我写了这个 MySQL 存储过程,但我一直收到这个语法错误 #1064 - You have an error in your SQL syntax; check the manual that
我试图在我的场景中显示特定的奖牌,这取决于你的高分是基于关卡的目标。 // Get Medal Colour if levelHighscore goalScore { sc
我必须维护相当古老的 Visual C++ 源代码的大型代码库。我发现代码如下: bIsOk = !!m_ptr->isOpen(some Parameters) bIsOk的数据类型是bool,is
我有一个从 MySQL 数据库中提取的动态产品列表。在 list 上有一个立即联系 按钮,我正在使用一个 jquery Modal 脚本,它会弹出一个表单。 我的问题是尝试将产品信息变量传递给该弹出窗
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
jQuery Core Style Guidelines建议两种不同的方法来检查变量是否已定义。 全局变量:typeof variable === "undefined" 局部变量:variable
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: “Variable” Variables in Javascript? 我想肯定有一种方法可以在 JavaScrip
在语句中使用多重赋值有什么优点或缺点吗?在简单的例子中 var1 = var2 = true; 赋值是从右到左的(我相信 C# 中的所有赋值都是如此,而且可能是 Java,尽管我没有检查后者)。但是,
我是一名优秀的程序员,十分优秀!