开发者

How can I reliably inject values into instances created outside of my control?

开发者 https://www.devze.com 2023-02-10 21:11 出处:网络
I have a class A with a method foo() that behaves differently depending on some configuration value: class A {

I have a class A with a method foo() that behaves differently depending on some configuration value:

class A {
    private transient Config config; // How do I set this field?

    public int foo() {
        return config.hasKey("bar") ? 1 : 2;
    }
}

A persistence framework like Hibernate creates i开发者_开发技巧nstances of A. How can I inject the current value of config into the instance?

Note: I'm using OJB, not Hibernate but the problem itself is always the same. It boils down to: I have some framework that creates instances for me. How can I reliably inject values into instances created outside of my control?

Performance is an issue here since millions of these objects are created.


While the answer is not exactly what you're looking for, Hibernate offers Interceptors for this type of processing. I'm not familiar with OJB, but you might find something similar.

You can get Spring to inject your services into your Hibernate instantiated instances, using AOP. You can also get Hibernate to do the same, using Interceptors.

See http://www.jblewitt.com/blog/?p=129

Taken from a previous answer of mine

Spring and the anemic domain model


config is part of the state of each A? if that's true then the value must be stored by your ORM too.


Just a thought... If it is for testing purpose, the easiest way is to mock foo() to return the value you want. If it is for production, then I might consider using AOP to intercept foo() and inject the value to it.

Okay, now that I see your config is transient... :)

class A {
    private ConfigService configService;
    private transient Config config;

    public Config getConfig() {
        if (config == null) {
            config = configService.getConfig();
        }
        return config;
    }

    public int foo() {
        return getConfig().hasKey("bar") ? 1 : 2;
    }
}

class ConfigService {   
    // use this API to inject the value into config first
    public Config getConfig(...) { ... }
}

Will something like this work for you?


i do not know ,if this is helpful .From Hibernate EntityManager.

long parentId = 12;
EntityManager em ... 
Parent parent = em.getReference(Parent.class, parentId);
parent.setFoo(config);


If you need to do something like this in OJB, follow this pattern:

RowReaderDefaultImpl calls ClassHelper.buildNewObjectInstance() to create the objects it reads from the database. So you need to override RowReaderDefaultImpl.buildOrRefreshObject(). A property in OJB.properties allows you to inject your own implementation into the system.

Unfortunately, there is no way to override ClassHelper.buildNewObjectInstance() itself (it's public static).

ClassHelper.buildNewObjectInstance() is called in two more places:

org.apache.ojb.broker.cache.ObjectCacheTwoLevelImpl.CopyStrategyImpl.read(PersistenceBroker, Object) and org.apache.ojb.broker.metadata.SuperReferenceDescriptor.SuperReferenceField.getObjectWithDeclaredSuperClass(Object) Not sure what they do; our project doesn't need them.

If you need to override those two as well, you will have to patch the sources of OJB.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号