web-dev-qa-db-fra.com

Comment câbler automatiquement un objet au printemps dans un objet créé avec new

tout ce que je veux faire est de câbler automatiquement le champ backgroundGray dans la classe NotesPanel, mais tout ce que je reçois est l'exception ci-dessous.

Alors, la question est de savoir comment le câbler correctement? Ça me rend vraiment fou parce que c'est probablement quelque chose de très stupide que je fais mal ...

merci pour toute aide! Thorsten

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'notepad' defined in class path resource [Beans.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [notepad.Notepad]: Constructor threw exception; nested exception is Java.lang.NullPointerException
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [notepad.Notepad]: Constructor threw exception; nested exception is Java.lang.NullPointerException
Caused by: Java.lang.NullPointerException
    at notepad.NotesPanel.<init>(NotesPanel.Java:23)
    at notepad.Notepad.<init>(Notepad.Java:18)

Bloc-notes de classe:

package notepad;

import Java.awt.BorderLayout;
import Java.awt.Dimension;

import javax.swing.JFrame;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Notepad
{

  public Notepad()
  {
    JFrame frame = new JFrame();
    frame.setLayout(new BorderLayout());
    frame.add(new NotesPanel(), BorderLayout.CENTER);

    frame.setPreferredSize(new Dimension(1024, 768));
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
  }

  public static void main(String[] args)
  {

    ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
    context.getBean("notepad");

  }
}

Classe Notespanel:

package notepad;

import Java.awt.BorderLayout;

import javax.swing.JPanel;
import javax.swing.JTextPane;

import org.springframework.beans.factory.annotation.Autowired;

public class NotesPanel
    extends JPanel
{
  JTextPane tPane = new JTextPane();

  @Autowired
  private BackgroundGray backgroundgray;

  public NotesPanel()
  {
//    backgroundgray = new BackgroundGray();
//    backgroundgray.setGray("200");
    setLayout(new BorderLayout());
    tPane.setBackground(backgroundgray.getGrayObject());
    add(tPane, BorderLayout.CENTER);
    tPane.setText("Fill me with notes... ");
  }

}

Contexte de la classe Gris:

package notepad;

import Java.awt.Color;

public class BackgroundGray
{
  String gray;

  public BackgroundGray()
  {
    System.out.println("Background Gray Constructor.");
  }

  public String getGray()
  {
    return gray;
  }

  public void setGray(String gray)
  {
    this.gray = gray;
  }

  public Color getGrayObject()
  {
    int val = Integer.parseInt(gray);
    return new Color(val, val, val);
  }

}

Beans.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <context:annotation-config />

    <bean id="notepad" class="notepad.Notepad"/>

    <bean id="backgroundgray" class="notepad.BackgroundGray" autowire="byName">
        <property name="gray" value="120"></property>
    </bean>
</beans>
13
user1119859

Support Spring @Autowire, ... uniquement pour Spring Beans. Normalement, une classe Java devient un bean Spring quand elle est créée par Spring, mais pas par new.

Une solution de contournement consiste à annoter la classe avec @Configurable Mais vous devez utiliser AspectJ (temps de compilation ou ondulation du temps de chargement)!

@see en utilisant @Configurable de Spring en trois étapes faciles pour une courte instruction étape par étape.

22
Ralph

Lorsque vous créez un objet par new, autowire\inject ne fonctionne pas ...

comme solution de contournement, vous pouvez essayer ceci:

créez votre bean modèle de NotesPanel

<bean id="notesPanel" class="..." scope="prototype">
    <!-- collaborators and configuration for this bean go here -->
</bean>

et créer une istance de cette façon

context.getBean("notesPanel");

PROTOTYPE : Ceci étend une définition de bean unique pour avoir un nombre quelconque d'instances d'objet.

6
Xstian

Je partage avec vous un exemple. J'espère que vous l'aimez :)

public class Main {
    public static void main(String args[]) {


        Java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager
                            .setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                new Ihm().setVisible(true);
            }
        });
    }
}

Mon bean de configuration:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ComponentScan("com.myproject.configuration")
@PropertySource("classpath:/application.properties")
public class Config {

    @Bean
    public Configurator configurator() {
        return new Configurator();
    }

}

Mon Java swing ihm qui utilise mon bean de configuration:

public class Ihm extends JFrame {

    private MyConfiguration configuration;

    public SmartRailServerConfigurationFileIhm() {

        try {
            ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
            configurator = context.getBean(MyConfiguration.class);
        } catch (Exception ex) {

        }
        System.out.println(configuration);

        ...
        ...
    }
}

Le problème est ici:

frame.add (nouveau NotesPanel (), BorderLayout.CENTER);

vous créez un nouvel objet pour la classe NotesPanel dans le constructeur de la classe Bloc-notes.

Le constructeur est appelé avant la méthode main, donc le contexte Spring n'a pas encore été chargé.

Lors de l'instanciation de l'objet pour NotesPanel, il ne peut pas câbler automatiquement BackgroundGray car le contexte Spring n'existe pas à ce moment.

1
Alfonso Pinto

Vous pouvez exécuter DI sur n'importe quelle instance, qu'elle soit gérée par Spring ou créée avec new.

Pour ce faire, utilisez le code suivant ...

AutowireCapableBeanFactory awcbf = applicationContext.getAutowireCapableBeanFactory();
awcbf.autowireBean(yourInstanceCreatedWithNew);

C'est également un excellent moyen d'introduire Spring dans une application développée à l'origine sans Spring - car elle vous permet d'utiliser Spring où vous le souhaitez sans avoir à convertir chaque classe de l'application en un bean Spring (car généralement, vous pouvez ' t utiliser un haricot de printemps sans haricot de printemps).

0
Rodney P. Barbati