beanFactory design patterns Bean life cycle of nonsense, ha ha

EDITORIAL words

Intended audience: those with some experience, this is not for beginners, because it may not understand what I'm saying

Article thinking: do not start a blog just like other articles like, Bean's life cycle, source code interpretation (you stick a bunch of source code). Personally feel should be driven by the question, why is the emergence of BeanFactory, why is there life cycle.

text

We started using the bean are simple bean, such as vo, po, entity, dto, so we are playing

XXEntity xxEntity = new XXEntity();
xxEntity.setPropA("字符串");

There may be a behind a complex bean, which has as an object property, you need to set the value at the time of construction or post-construction (Example only, not seriously), as

// 构建序列化实例,这里 Serializable 是接口,使用接口的好处是在使用别的序列化时,不需要修改 jedis 类
Serializable fastJsonSerizlizable = new FastJsonSerizlizable();

// 构建目标 jedis 实例 ,需要先构建序列化对象 
Jedis jedis = new Jedis();
jedis.setSerializable(fastJsonSerizlizable);

Then came serviceA serviceB classes and classes that need to use redis, I can not go to jedis example of the process of writing it again in each class which, when experienced students will write a class tool to create jedis, like this

public BeanUtil {
    // 可以把创建序列化单拿出来,因为除了 redis 需要序列化之外,kafka 也需要序列化
    public static Serializable createSerializable(){
        return new FastJsonSerizlizable();
    }
    
    public static Jedis createJedis(){
        Jedis jedis = new Jedis();
        jedis.setSerializable(createSerializable());
        return jedis;
    }
}

// 这里我 serviceA,serviceB 都可以使用 createJedis 来直接获取 jedis 实例 ,而不需要关心创建细节,使用哪个序列化等问题

There are several problems in the code above

  • Jedis is created every time you use an object, and each individual will jedis subject to a Serializable object, but fastJson serialization and jedis types of things are just tools, an instance of enough already.
  • Jedis can not be configured
  • Not allow users to create BeanUtil instance, improved code as follows
public BeanUtil {
    // 禁用 BeanUtil 构建 
    private BeanUtil(){}
    
    // 这里我们可以使用 bean 的全路径 => bean 实例来缓存 bean 
    static Map<String,Object> beansCache = new ConcurrentHashMap<String,Object>();
    
    static{
        // 初始化时,在内容缓存这些 bean 的实例,因为 jedis 依赖于 serializable ,需要需要先创建 serializable
        Serializable serializable = createSerializable();
        beansCache.put(Serializable.class.getSimpleName(),serializable);
        Jedis jedis = createJedis();
        beansCache.put(jedis.class.getSimpleName(),jedis);
    }
    
    static Serializable createSerializable(String type){
        Serializable serializable =  beansCache.get("serializable");
        if(serializable != null)return serializable;
        
        switch(type){
            case "kryo":    // kryo 不能用单例,请忽略本问题,示例而已
                return new KryoSerializable();
            case "protostuff":
                return new protostuffSerializable();
            default:
                return new FastJsonSerizlizable();
        }
    }
    
    static Jedis createJedis(String serializableType){
        Jedis jedis = new Jedis();
        Serializable serializable = beansCache.get("serializable");
        jedis.setSerializable(serializable);
        return jedis;
    }

    //然后对外提供获取 Bean 的方法 
    public static Object getBean(String beanName){
        return beansCache.get(beanName);
    }
    
    public static T getBean(Class<T> type){
        return beansCache.get(type.getSimpleName());
    }

}

But if the writing of this class is Xiao Ming, after a period of time this class will be initialized operate a large number of createXx and XX, and the degree of dependence is very complex, then Xiao Ming think it is time to optimize the wave, so Xiao Ming thought One solution, defines a syntax xml

Bean tag used to define a bean, bean each has a unique id information, using the property to define its properties, if it is complicated to use REF attribute, parsing the xml obtain a complete dependency graph bean

<beans>
    <bean id="serializable" class="com.xx.FastJsonSerizlizable" />
    
    <bean id="jedis" class="com.xx.Jedis">
        <property name="host" value="localhost" />
        <property name="serializable" ref="serializable"/>
    </bean>
</beans>

Then there is a dependency problem, I created jedis first create serializable, but xml bean defined serializable is written in the front of the file, Xiao Ming thought of a way, first with pre-existing string ref, all put a bean definition, like this

Map<String,BeanDefinition> beanDefinitions = new HashMap();

Then parse it into a dependency tree, so that you can construct the first leaves, then the object is constructed layer by layer, but there is also a tricky situation, and that is a circular dependency

root

  |-jedis

    |- serializable

What it is a circular dependency, the simplest A depends on B, B is dependent on A, middle or last more dependent on the formation of a ring, ABCA

The most original solution is such that we can first use the constructor to create them all out, you can not be there with their constructors, and then set the target set by property values. Therefore, the configurations of the injection, the property by way of circular dependency can be resolved.

Then our BeanUtil become such, can not think of a utility class called instead entity classes Factory

public BeanFactory {
    
    Map<String,BeanDefinition> beanDefinitions = new HashMap();
    
    // 这里我们可以使用 bean 的全路径 => bean 实例来缓存 bean 
    Map<String,Object> beansCache = new ConcurrentHashMap<String,Object>();
 
    {
        // 加载 xml bean 配置文件
        beanDefinitions = loadXml(contextConfigurations:String []);
        
        //实例化所有 bean 
        beansCache = instanceBeans(beanDefinitions);
    }
    
    //然后对外提供获取 Bean 的方法 
    public  Object getBean(String beanName){
        return beansCache.get(beanName);
    }
    
    public  T getBean(Class<T> type){
        return beansCache.get(type.getSimpleName());
    }
}

This seems to have perfectly adequate, but this time programmer A question I need to initialize when one of my classes, I want to get some resources such as connection, files, resources, and want to reclaim resources at class destruction, However, according to the above did not have any way to do it.

Little said, this is easy to handle, I offer several interfaces to you, you realize what I'll be when the instance of the Bean, if you find you have to implement an interface in the corresponding process where I can help you call it, so Xiaoming added two interfaces

public interface InitializingBean{
    void afterPropertiesSet() throws Exception;
}

public  interface DisposableBean{
    void destroy() throws Exception;
}

A programmer problem is resolved, then the programmer B said, Is there a way, can intercept all of the initialization process Bean, rather than my current class, I want every service into a proxy class, I want to add transaction service in the method.

Little said, Well, I put the bean properties are injected over, and then to the bean to you, you decorate the bean and then back to me, so Xiao Ming provided out of such an interface, and is initialized before the bean initialization after, you can come to modify bean, do not pay attention, this is for the global, not your personal bean, to do the filtering operation

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException ;
    
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
}

C programmers and ask questions at this time, I created a BeanA but how I can get BeanC ah, I want to see some of the properties of c.

Fiction that really annoying, I just put the map gave Hello, no, I gave Hello BeanFactory, and so with this interface

public interface BeanFactoryAware{
    void setBeanFactory(BeanFactory beanUtil);
}

This will then D asked, when I setBeanFactory, and I created a global processor implemented, or are in the execution after the big head.

Under Little said, I'm finishing order of execution, we take a name, called the bean's life cycle, the way and then provide several practical interface, the bean name I have not told How about you, so finishing the life cycle of the following

反射创建 Bean 
填充对象属性
BeanNameAware.setBeanName();
BeanFactoryAware.setBeanFactory ();
BeanPostProcessor.postProcessBeforeInitialization(); 多个
InitializingBean.afterPropertiesSet()
BeanPostProcessor.postProcessAfterInitialization(); 多个
DisposableBean.destory()

E said the programmer, xml configuration too much trouble, jdk1.5 do not have a comment, I like to add a logo on, you scan my class, help me create an instance of chanting

Then I need, I add a logo on the property, you can also find dependent classes depending on the type, and then created the corresponding instance, help me put the value into them just fine, if the process of creating this kind of comparison complex, to create my own, then I put it back to you, I define a method, add a logo Bean, you read into the container.

So Xiao Ming also added @Componentto represent the components @Beanto represent the custom instance is created, @Autowiredto inject the object @PostConstructto perform the initialization class @PreDestroydestroy class to do the work, the life cycle of the class become so

反射创建 Bean 
填充对象属性
BeanNameAware.setBeanName();
BeanFactoryAware.setBeanFactory ();
BeanPostProcessor.postProcessBeforeInitialization(); 多个
PostConstruct
InitializingBean.afterPropertiesSet()
BeanPostProcessor.postProcessAfterInitialization(); 多个
PreDestroy
DisposableBean.destory()

But for compatibility with previous xml form, Xiao Ming then abstracted into the BeanFactory interface, providing getBean method, based on a single principle of duty, Bean BeanFactory should not resolve to do the work;

Then create an interface for loading Bean definition, there are two implementations XmlBeanRegistry, AnnotationBeanRegistry, loaded Bean defined after the merger, after taking into account also possible to add other registered bean ways, providing a one-time external interface

public interface BeanFactoryPostProcessor{
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

You can put your bean definitions written rules, instantiated as BeanDefinition I ask then send me a custom implementation can add your own custom bean into the container

Little promotion

Writing is not easy, I hope the support of open source software, and my gadgets, welcome to gitee point star, fork, put bug.

Excel common import and export, support Excel formulas
blog address: https://blog.csdn.net/sanri1993/article/details/100601578
gitee: https://gitee.com/sanri/sanri-excel-poi

Use the template code, the gadget generate code from the database, and some projects can often be used in the
blog address: https://blog.csdn.net/sanri1993/article/details/98664034
gitee: https://gitee.com/ sanri / sanri-tools-maven

Guess you like

Origin www.cnblogs.com/sanri1993/p/11816411.html