月度归档:2012年11月

静态方法中使用Spring注入实例

以前在『freemarker模板中使用自定义函数』中写过:“在一些spring接管对象生命周期管理的应用中,如果自定义函数实现类中用到了spring的依赖注入,会出现注入失败的情况。这是因为自定义函数的实例是在ftl模板中new出来的,就好像在代码中直接new Object()一样,没有启用spring的依赖管理”。其实后来发现这个问题有解决方法,例如可在TemplateMethodModel接口的实现类中调用某个类的静态方法,而这个静态方法中使用了我们需要的由Spring管理的实例。

静态方法中可通过以下方法使用Spring注入的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TramUtil {
    private static TramUtil trampo;
    private IUserDao userDao = null;
 
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }
 
    public void init() {
        trampo = this;
        trampo.userDao = this.userDao;
    }
 
    public static String getNameById(String id) {
        return trampo.userDao.getNameById(id);
    }
}

这里,TramUtil是由Spring管理的普通实例,它有一个静态方法getNameById(),可在程序外部通过类名.方法名调用,因为Java中静态方法不能直接访问非静态成员(userDao)和非静态方法,因此需要再声明一个静态的成员trampo,通过它来间接调用userDao,而这个userDao就是我们希望在静态方法中使用的由Spring管理的bean实例。

另外Spring配置文件(application-context.xml)中要把依赖管理好,例如:

1
2
3
4
<bean id="userTenantDao" class="com.zju.dao.impl.UserDaoImpl" />
<bean id="tramUtil" class="com.zju.util.TramUtil" init-method="init">
         <property name="userDao" ref="userDao"/>
</bean>

结合XML配置信息,上面程序中各个部分的执行流程为,首先Spring在实例化TramUtil类时会默认先调用一次TramUtil无参构造方法,根据配置,Spring在注入userDao属性时会调用TramUtil的setUserDao方法。等这两个步骤完成后,调用init-method方法,此时,因为TramUtil实例已构造完成,userDao属性注入完毕,init方法中this和this.userDao都已经是对象的有效引用。所以在流程和语法上就完成了静态方法中使用Spring注入实例的实现。

文章开头ftl文件中使用自定义函数的场景里,可在TemplateMethodModel接口的实现类中通过TramUtil.getNameById()来实现对Spring bean(例子中的userDao属性)的调用。

--EOF--