How to inject Mapper in multi-threaded situations, and how to inject other Spring annotated classes into classes instantiated by yourself

Under multithreading, you will find that Spring's automatic injection fails. The reason is that Spring thinks it is dangerous to do so under multithreading. If you are used to using the framework, then we all know that the default is singleton, that is in multithreading. How to inject Mapper for us to use?

In a multi-threaded project, I also encountered this problem, and the instantiation of the classes above my mapper interface was instantiated by myself through java reflection. I only added the @Mapper annotation when the Mapper interface was used. The direct problem is that if I write the usual @Resouce in the business class to inject the Mapper, the mapper is Null, which is completely understandable, because my business class is not annotated, and it is not handed over to spring for management. It is instantiated by itself Yes, this causes the mapper to fail to be injected, so how do I call the mapper? Oh roar! You can declare a mapper variable in the business class, and then add an initialization method during reflection initialization

Note: The situation I discussed is that the general business class is instantiated by itself, and some classes are managed by spring

You might say: Is the original poster sick? Part of it is instantiated by itself, and part of it is managed by spring, isn’t it messy

No, Java reflection is the first way to dynamically obtain and instantiate classes;

The second is the ordinary springmvc project in the past. We remember that there will be a lot of configuration files. A bean configuration can add the attribute configuration you want during initialization.

We have evolved the method of configuration files;

Many of the current frameworks, such as springboot, springcloud, etc., handle these tasks by themselves. We don't have to care about it. We write more about business;

In the final analysis, they are all based on java reflection.

The benefits of java reflection: You can instantiate your specific class at the code level, such as instantiating according to the fuzzy class name, etc., and you can do anything during the instantiation.

Not much to say, my situation is:

I instantiated the matching interface class under the com.skxx.work.busi package. At the same time, notice that I added an initMapper() method here. This method is to configure the mapper for my business class.

Look at my business class:

My UserLogic did not add any annotations. As I said before, this class was instantiated by myself through the above reflection and was not managed by spring.

But my Mapper interface is managed by spring, so how do we get it next? Through the spring context, here is a tool method to get any bean in your context. The above code does not have much to do with you, just for everyone to understand the situation, the following tool code is not a picture

This is my mapper, which is managed by spring:

 Tool class: get any bean that has been instantiated through the context

package com.skxx.config.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @program: coalpreparation
 * @description:  解决在多线程情况下,非注解实例化类时,无法注入mapper的问题
 *              因为类的实例化并不没有交给spring,所以要自己手动去获取mapper
 * @author: Mr.MYR(ClearLoveQ)
 * @create: 2020-04-21 14:24
 **/
@Component
public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringContextUtil.applicationContext == null) {
            SpringContextUtil.applicationContext = applicationContext;
        }
    }

    /**
     * 获取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean.
     *
     * @param name
     *            Bean's name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean.
     *
     * @param clazz
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

 

At this point, I believe you may have a deeper understanding of spring, and I wish you all keep moving forward on the road of code.

 

Guess you like

Origin blog.csdn.net/ClearLoveQ/article/details/105661353
Recommended