如何在使用new创建的对象中在spring中自动装配对象

时间:2014-08-13 10:38:45

标签: java spring autowired

我想要做的就是在NotesPanel类中自动连接字段backgroundGray,但我得到的只是下面的例外。

所以,问题是,如何正确地自动装配它?它真的让我发疯,因为它可能是非常愚蠢的我做错了......

感谢您的帮助! 的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)

班级记事本:

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");

  }
}

Class 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... ");
  }

}

类BackgroundGray:

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>

5 个答案:

答案 0 :(得分:19)

Spring支持@Autowire,...仅适用于Spring Beans。通常,Java类在由Spring创建时变为Spring Bean,而不是由new创建。

一个workarround是用@Configurable注释类,但你必须使用AspectJ(编译时或加载时挥手)!

@see Using Spring's @Configurable in three easy steps进行简短的逐步说明。

答案 1 :(得分:6)

当你用new创建一个对象时,autowire \ inject不会工作......

作为解决方法,你可以试试这个:

创建NotesPanel的模板bean

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

以这种方式创建一个istance

context.getBean("notesPanel");

PROTOTYPE :这可以使单个bean定义包含任意数量的对象实例。

答案 2 :(得分:1)

问题在于:

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

您正在类Notepad的构造函数中为类NotesPanel创建一个新对象。

构造函数在方法main之前调用,因此尚未加载Spring上下文。

在为NotesPanel实例化对象时,它无法自动连接BackgroundGray,因为当时Spring上下文不存在。

答案 3 :(得分:1)

我与你分享一个例子。 我希望你喜欢它:)。

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);
            }
        });
    }
}

我的配置bean:

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();
    }

}

我使用配置bean的java swing ihm:

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);

        ...
        ...
    }
}

答案 4 :(得分:0)

您可以在任何实例上执行DI,无论是Spring托管还是使用new创建的实例。

为此,请使用以下代码...

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

这也是将Spring引入最初没有使用Spring开发的应用程序的好方法-因为它使您可以在需要的地方使用Spring,而不必将应用程序中的每个类都转换为Spring bean(通常,您不能在没有Spring Bean的情况下使用Spring Bean。