如何使用@Autowired在新线程中注入对象?

时间:2018-11-01 18:23:03

标签: java spring multithreading autowired

我在使用Spring进行依赖注入时遇到了一个问题,

这是我的服务

package IntegraLogger.Controller.Service;

//imports

@Component
public class PlcService extends ServiceBase<Plc, Long, PlcRepository> {

    @Autowired
    public PlcService(PlcRepository repository) {
        super(repository);
    }

    private List<TcpConnection> connections = new ArrayList<>();

    public List<TcpConnection> getConnections() {
        return connections;
    }


    public void test() {
        System.out.println("works!");
    }
}

在这里,我所有的 @Autowired 依赖项都能正常工作!

package IntegraLogger.Enviroment;
//imports

@Component
public class ApplicationStartup implements 
ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    private PlcService plcService;

    @Autowired
    private ThreadPool pool;

    @Autowired
    private UserService userService;

    @Autowired
    private ItagConfigService itagConfigService;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        //just prepare the enviroment for develop running
            startupEnviroment();
    }

    private void startupEnviroment() {
        //TODO this is a temporary enviroment preparation
        User user = new User();
        user.setName("William Douglas");
        user.setEmail("wdouglas@test.com");
        user.setPassword("TeSt");
        user.setPhoneNumber("1234567890");

        userService.save(user);

        Plc plc = new Plc();
        Plc plc2 = new Plc();
        plc.setIp("192.168.0.217");
        plc2.setIp("192.168.0.217");
        plc.setSlot(0);
        plc2.setSlot(0);
        plc.setDescription("PLC_Teste01");
        plc2.setDescription("PLC_Segundo");
        ItagConfig itagConfig1 = new ItagConfig("Bool1", "Tag Booleano de mudança rápida", 1);
        ItagConfig itagConfig2 = new ItagConfig("AlarmTest", "PLC 2 - Alarme de Teste", 1);
        ItagConfig itagConfig3 = new ItagConfig("wstring", "Palavra lida", 1);
        ItagConfig itagConfig4 = new ItagConfig("timmer1.ACC", "Valor acumulado de tempo", 5);
        ItagConfig itagConfig5 = new ItagConfig("wdouglas", "valor inteiro eu acho", 2);
        ItagConfig itagConfig6 = new ItagConfig("xSecCounter", "Contador em segundos", 2);
        ItagConfig itagConfig7 = new ItagConfig("Body1HFlow", "PLC 2 - Variável real aleatória", 5);
        itagConfig1.setListener(ListenersIndex.EMAIL);
        itagConfig7.setListener(ListenersIndex.PERSIST);
        plc.getItagConfigs().add(itagConfig1);
        plc2.getItagConfigs().add(itagConfig2);
        plc.getItagConfigs().add(itagConfig3);
        plc.getItagConfigs().add(itagConfig4);
        plc.getItagConfigs().add(itagConfig5);
        plc.getItagConfigs().add(itagConfig6);
        plc2.getItagConfigs().add(itagConfig7);

        itagConfigService.save(itagConfig1);
        itagConfigService.save(itagConfig2);
        itagConfigService.save(itagConfig3);
        itagConfigService.save(itagConfig4);
        itagConfigService.save(itagConfig5);
        itagConfigService.save(itagConfig6);
        itagConfigService.save(itagConfig7);

        plcService.save(plc);
        plcService.save(plc2);

        PlcThread plcThread = new PlcThread(plc);

        pool.addPlcThread(plcThread);
        System.out.println(plcThread);
        Thread thread = new Thread(plcThread, plc.getDescription());
        pool.addThread(thread);
        thread.start();

        PlcThread plcThread2 = new PlcThread(plc2);
        pool.addPlcThread(plcThread2);
        System.out.println(plcThread2);
        Thread thread2 = new Thread(plcThread2, plc2.getDescription());
        pool.addThread(thread2);
        thread2.start();
    }
}

请注意,我启动了新线程,这些线程调用了一些需要访问我的服务的方法,但是这些依赖项为null ...

这里是一个例子:

package IntegraLogger.Enviroment;

//imports

@Component
public class PlcConnection {

    @Autowired
    private PlcService plcService;

    public Connection plcConnect(Plc plc) {
        try {
            TcpConnection con = new TcpConnection(plc.getIp(), plc.getSlot());
            RegisterSession register = new RegisterSession();
            con.execute(register);
            con.setSession(register.getSession());
            System.out.println(plc.getDescription() + " connection is open: " + con.isOpen());
            plcService.getConnections().add(con);
            return con;
        } catch (Exception e) {
            System.out.println("Controller " + plc.getDescription() + " - IP: " + plc.getIp() + " not connected");
            e.printStackTrace();
            return null;
        }
    }
}

当我启动一个新线程并尝试访问任何@Autowired依赖项时,该对象为null,但是当我在主线程中访问时是可以的。

Spring是否有解决此问题的方法?如果没有,有人知道我该如何解决?

非常感谢!

编辑: 当我创建一个PlcThread时,构造函数将调用plcConnection:

    PlcThread plcThread = new PlcThread(plc);

    pool.addPlcThread(plcThread);
    System.out.println(plcThread);
    Thread thread = new Thread(plcThread, plc.getDescription());
    pool.addThread(thread);
    thread.start();

这是PlcThread类:

package IntegraLogger.Application;
//imports

public class PlcThread implements Runnable, ConnectionFailListener {

    private PlcConnection plcConnection = new PlcConnection();

    private TagEmail tagEmail = new TagEmail();
    private TagPersist tagPersist = new TagPersist();
    private TagLogger tagLogger = new TagLogger();
    private Plc plc;
    private List<Tag> tags = new ArrayList<>();
    private Scanner scanner;
    private boolean connectionMonitor;

    public PlcThread(Plc plc) {
        this.plc = plc;
        Connection connection = plcConnection.plcConnect(plc); // 
        this.scanner = new Scanner(connection, 5, this);
        this.connectionMonitor = true;
    }


    public boolean checkConnection() {
        EtherNetIP netIP = new EtherNetIP(plc.getIp(), plc.getSlot());

        try {
            netIP.connectTcp();
            netIP.close();
            return true;
        } catch (Exception e) {
            System.out.println("Fail to connect! Device description: '" + plc.getDescription() + "' IP: " + plc.getIp());

            e.printStackTrace();
            return false;
        }
    }

    public void scan() {


        for (ItagConfig itagConfig : plc.getItagConfigs()) {
            Tag tag = scanner.add(itagConfig.getTimeUpdate(), itagConfig.getName());
            for (ListenersIndex listenersIndex : itagConfig.getListeners()) {

                if (listenersIndex.equals(ListenersIndex.EMAIL)) {
                    tag.addListener(tagEmail);
                }
                if (listenersIndex.equals(ListenersIndex.LOGGER)) {
                    tag.addListener(tagLogger);
                }
                if (listenersIndex.equals(ListenersIndex.PERSIST)) {
                    tag.addListener(tagPersist);
                }
            }
            this.tags.add(tag);

        }
    }


    @Override
    public void run() {
        boolean b = true;
        System.out.println("Thread " + plc.getDescription() + " has started!");
        scan();
        while (b) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!checkConnection() || !connectionMonitor) {
                b = false;
                this.scanner.stop();
            }
        }
        System.out.println("Thread " + plc.getDescription() + " FINISHED");

    }

    @Override
    public void actionFailure(TagList tagList) {
        System.out.println("Error try out  --------------------------------------------------");

        this.connectionMonitor = false;

    }

    public Plc getPlc() {
        return plc;
    }
}

此后,所有自动装配对象均有效,它们全部为空... 我认为问题出在上下文上,因为这是一个新线程,但我不确定任何事情...

谢谢

0 个答案:

没有答案
相关问题