2014-01-04 5 views
0

Я создаю финансовое приложение с использованием Swing with Spring. В одной части моего приложения у меня есть JList, содержащий JLabel для каждого Account в приложении. Когда нажата кнопка JLabel, я хочу отобразить JPanel типа AccountTab в пределах JTabbedPane. Все это выполняется в следующем контроллере.Autowiring in Prototype Bean

@Component 
public class AccountListController extends MouseAdapter implements MouseListener { 

    @Autowired 
    private AccountService accountService; 

    @Autowired 
    private MainFrameView mainFrameView; 

    @Autowired 
    private ApplicationContext context; 

    @Override 
    public void mouseClicked(MouseEvent e) { 
     if (e.getSource() instanceof JList) { 
      JList list = (JList) e.getSource(); 
      JTabbedPane tabbedPane = this.mainFrameView.getTabbedPane(); 

      SidebarItem item = (SidebarItem) list.getModel().getElementAt(list.getSelectedIndex()); 
      Account account = accountService.findById(item.getValue()); 

      if (tabbedPane.indexOfTab(account.getName()) == -1) { 
       AccountTab panel = context.getBean(AccountTab.class); 
       panel.addTransactions(account.getTransactions()); 
       panel.getSplitPane().setDividerLocation(500); 
       tabbedPane.addTab(item.getTitle(), panel); 
      } 

      tabbedPane.setSelectedIndex(tabbedPane.indexOfTab(account.getName())); 
     } 
    } 

} 

В AccountTab изменения для каждого JLabel щелкнул, так что я сделал AccountTab прототип фасоли, поэтому я получаю новый экземпляр для каждой учетной записи. Чтобы сделать работу прототипа, мне нужно использовать context.getBean(AccountTab.class). Вот AccountTab код:

@Component 
@Scope("prototype") 
public class AccountTab extends JPanel { 

    @Autowired 
    private AccountTransactionPane transactionPane; 

    private static final long serialVersionUID = 1L; 
    private JTable table = new JTable(); 
    private JSplitPane splitPane; 

    public AccountTab() { 
     this.setLayout(new BorderLayout()); 
     JScrollPane scrollPane = new JScrollPane(this.table); 
     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, transactionPane); 
     splitPane.setEnabled(false); 
     this.add(splitPane, BorderLayout.CENTER); 
    } 

    public void addTransactions(List<AccountTransaction> transactions) { 
     this.table.setModel(new AccountTransactionTableModel(transactions)); 
    } 

    //omitted rest of code 
} 

Вы заметите, я пытаюсь autowire боб типа AccountTransactionPane однако, компонент не правильно autowired, она равна нулю. Вот код для AccountTransactionPane:

@Component 
public class AccountTransactionPane extends JPanel { 

    private static final long serialVersionUID = 1L; 

    JTabbedPane tabbedPane = new JTabbedPane(); 
    private JPanel withdrawlTransactionPane = new DepositTransactionPane().build(); 
    private JPanel depositTransactionPane = new DepositTransactionPane().build(); 
    private JPanel transferTransactionPane = new DepositTransactionPane().build(); 

    public AccountTransactionPane() { 
     this.setLayout(new BorderLayout()); 
     tabbedPane.addTab("Withdrawl", this.withdrawlTransactionPane); 
     tabbedPane.addTab("Deposit", this.depositTransactionPane); 
     tabbedPane.addTab("Transfer", this.transferTransactionPane); 
     this.add(tabbedPane, BorderLayout.CENTER); 
    } 
    //rest of class omitted 
} 

У меня есть одна конкретная проблема и один общий. Во-первых, AccountTransactionPane не автоувеличивается в фазе AccountTab. Я не уверен, почему, как я могу получить фасоль AccountTransactionPane для автоподготовки в пределах AccountTab?

Моя вторая проблема более общая, я все-таки автолюбитель. Кажется, что все должно быть фасолью. Я попал в шаблон создания контроллера (bean), ввел пользовательский интерфейс (bean), затем ввел другой контроллер (bean), который используется в качестве слушателя, внутри этого контроллера я ввожу сервис (bean). Это нормально? Я не могу найти хороших примеров больших приложений Swing with Spring, которые помогут мне.

UPDATE: Spring Java Config

@Configuration 
@EnableJpaRepositories(basePackages="rhcloud.blog.tothought.data.repositories") 
@EnableTransactionManagement 
@ComponentScan({"rhcloud.blog.tothought.data", "rhcloud.blog.tothought.controllers", "rhcloud.blog.tothought.view.ui"}) 
public class ApplicationConfiguration { 

     private static final String H2_JDBC_URL_TEMPLATE = "jdbc:h2:file:~/MyFinances/data;TRACE_LEVEL_FILE=3;TRACE_LEVEL_SYSTEM_OUT=3"; 

     @Bean 
     public DataSource dataSource(){ 
      JdbcDataSource ds = new JdbcDataSource();  
      ds.setURL(H2_JDBC_URL_TEMPLATE); 
      ds.setUser("sa"); 
      ds.setPassword("sa"); 

      return ds; 
     } 

     @Bean 
     public EntityManagerFactory entityManagerFactory() { 

     HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     vendorAdapter.setGenerateDdl(true); 
     vendorAdapter.setShowSql(true); 
     vendorAdapter.setDatabase(Database.H2); 

     LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 
     factory.setJpaVendorAdapter(vendorAdapter); 
     factory.setPackagesToScan("rhcloud.blog.tothought.data.entities"); 
     factory.setDataSource(dataSource()); 
     factory.afterPropertiesSet(); 

     return factory.getObject(); 
     } 

     @Bean 
     public PlatformTransactionManager transactionManager() { 
     JpaTransactionManager txManager = new JpaTransactionManager(); 
     txManager.setEntityManagerFactory(entityManagerFactory()); 
     return txManager; 
     } 

     /** 
     * See: http://stackoverflow.com/questions/8434712/no-persistence-exception-translators-found-in-bean-factory-cannot-perform-excep 
     * @return 
     */ 
     @Bean 
     public HibernateExceptionTranslator hibernateExceptionTranslator(){ 
      return new HibernateExceptionTranslator(); 
     } 

     @Bean 
     public Application application(){ 
      return new Application(); 
     } 
} 
+0

весна никогда не будет вводить 'null' (не для бобов в любом случае). Отправьте конфигурацию своего контекста. –

+0

@SotiriosDelimanolis Я добавил конфигурацию в соответствии с запросом. Если я поместил 'System.out.println (transactionPane);' в конструкторе 'AccountTab' печатает' null' на консоли. Цените помощь. –

+0

please whats 'У меня есть JList, содержащий JLabel для каждой учетной записи', я надеюсь, что это неверно, это только неправильное описание – mKorbel

ответ

1

Процесс впрыска идет как это

  • Получить Class экземпляр для класса, чтобы создать компонент для
  • Либо получить Constructor или использовать Class#newInstance() для создания bean-компонента
  • Inject the bea n со всеми его целями @Autowired.

Ваш класс конструктор как

@Autowired 
private AccountTransactionPane transactionPane; 

... 

public AccountTab() { 
    this.setLayout(new BorderLayout()); 
    JScrollPane scrollPane = new JScrollPane(this.table); 
    splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, transactionPane); 
    splitPane.setEnabled(false); 
    this.add(splitPane, BorderLayout.CENTER); 
} 

transactionPane Так, очевидно, будет в конструкторе null. Весна не обходила его инъекцией. Рассмотрите возможность использования аннотированного метода @PostConstruct, если есть некоторая инициализация, которую вам нужно сделать с инжекционными компонентами.


Моя вторая проблема является более общим, я все автоматического связывания. Это кажется, что все должно быть фасолью.Я попал в шаблон , чтобы создать контроллер (bean), ввести пользовательский интерфейс (bean), затем ввести другой контроллер (bean), который используется в качестве слушателя, внутри этого контроллера я ввожу сервис (bean). Это нормально?

Для вашего приложения должна быть одна точка входа, которая загружает Spring ApplicationContext. Каждый другой компонент (и его зависимости) должен управляться этим ApplicationContext.

+0

Итак, добавьте аннотированный метод «PostConstruct», выполните операции ui, такие как создание splitpane ? –

+0

@kevin Я не знаю Swing очень хорошо, но не похоже, что вам что-то нужно сделать в конструкторе. Так да. –

+0

Работает как очарование! Спасибо, что выручил меня. –

1

Использование init метод построения панели вместо Ctor. Autowiring выполняется после строительства.

т.е.

@PostConstruct 
public void init() { 
    this.setLayout(new BorderLayout()); 
    JScrollPane scrollPane = new JScrollPane(this.table); 
    splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, transactionPane); 
    splitPane.setEnabled(false); 
    this.add(splitPane, BorderLayout.CENTER); 
} 

Вы также можете вводить transactionPane в CTOR:

@Autowired 
    public AccountTab(AccountTransactionPane transactionPane) { 
    ... 
} 
+0

Спасибо за предложение метода PostConstruct, но я думаю, что это должно быть в 'AccountTab' вместо' AccountTransactionPane'. –

+0

О, да, я скопировал с неправильного места ... –

Смежные вопросы