Using Java Spring injection with `public static final` objects (for Jakarta Unstandard)

时间秒杀一切 提交于 2020-02-24 05:45:07

问题


Disclaimer: I understand that trying to use Spring to inject static variables is considered bad practice (and I know there are ways around it, e.g. here). So ultimately I plan to redesign, but am curious about possible solutions or workarounds.

I am using Jakarta's Unstandard tag library (particularly useConstants) to easily expose public static final objects to my JSP pages. I want these static objects to initialize themselves from my database, which means I need to inject a JDBC Template or Data Source. So I want something like:

public class MyGroup {

    // @Autowire or inject somehow?
    private static /*final?*/ NamedParameterJdbcTemplate jdbcTemplate;

    public static final MyGroup GROUP_A = new MyGroup("GROUP_A");
    public static final MyGroup GROUP_B = new MyGroup("GROUP_B");
    public static final MyGroup GROUP_C = new MyGroup("GROUP_C");

    // Instance fields
    private int id;
    private String name;
    private String description;

    /**
     * Construct a group
     */
    public MyGroup() {}

    /**
     * Construct a group using information from the database
     * @param key the key to match
     */
    public MyGroup(String key) {
        // Do DB stuff using injected JDBC template
        this.id = id_from_DB;
        this.name = name_from_DB;
        this.description = desc_from_DB;
    }
}

In my JSP, I could simply do ${MyGroup.GROUP_A.id} and anywhere else in the Java code I could just MyGroup.GROUP_B.getName().

So the problem is that these groups must be final for the Jakarta library to pick them up, but I can't static initialize them via Spring. Thoughts?


回答1:


This isn't a problem with spring so much as with a conflict between what you want and what java allows. You cannot delay the assignment of a static final property. It has to be set when the class is loaded. Therefore, by the time spring could inject, it is too late.

If you don't have to have it be final, you can open up some options.

Another possibility is it might be possible to create an aspect when intercepts the access of the property, and returns the value you want rather than the stored value. You could then inject the desired value into the aspect.

I've never done it before specifically with static properties, but I presume it is possible. It is not possible to use constant fields (static final fields bound to a constant string object or primitive value) as a JoinPoint since java requires those to be inlined, but since you are pointing to a non-String object, I think using an aspect could work.

To make sure spring injects into your aspect, make sure you tell spring about it via via something like this:

<bean id="someId" class="com.yourdomain.YourAspect" factory-method="aspectOf"/>


来源:https://stackoverflow.com/questions/23222468/using-java-spring-injection-with-public-static-final-objects-for-jakarta-unst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!