У меня есть следующий файл app-context.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="todo"/>
<bean id="mainFrame" class="todo.ui.MainFrame" init-method="init" lazy-init="true">
<property name="mainPanel">
<ref bean="mainPanel"/>
</property>
<property name="title">
<value>My To Do List</value>
</property>
</bean>
<bean id="mainPanel" class="todo.ui.BoxLayoutPanel"
init-method="init" lazy-init="true">
<property name="axis">
<!-- "1" corresponds to BoxLayout.Y_AXIS
Spring can access constants, but it's more complex -->
<value>1</value>
</property>
<property name="panelComponents">
<list>
<ref bean="itemScrollPane"/>
<ref bean="buttonPanel"/>
</list>
</property>
</bean>
<bean id="itemScrollPane" class="javax.swing.JScrollPane">
<constructor-arg>
<ref bean="itemTable"/>
</constructor-arg>
</bean>
<bean id="itemTable" class="javax.swing.JTable" depends-on="itemTableModel">
<property name="model">
<ref bean="itemTableModel"/>
</property>
</bean>
<bean id="buttonPanel" class="todo.ui.BoxLayoutPanel" init-method="init" depends-on="deleteButton" lazy-init="true">
<property name="axis">
<!-- "0" corresponds to BoxLayout.X_AXIS -->
<value>0</value>
</property>
<property name="panelComponents">
<list>
<ref bean="deleteButton"/>
<ref bean="addNewButton"/>
</list>
</property>
</bean>
<!-- <bean id="deleteButton" class="todo.ui.button.ActionListenerButton"
init-method="init">
<property name="actionListener">
<ref bean="deleteButtonActionListener"/>
</property>
<property name="text">
<value>Delete</value>
</property>
</bean> -->
<!-- <bean id="deleteButtonActionListener"
class="todo.ui.button.DeleteButtonActionListener">
<property name="list">
<ref bean="itemList"/>
</property>
<property name="table">
<ref bean="itemTable"/>
</property>
</bean> -->
<!-- <bean id="addNewButton" class="todo.ui.button.ActionListenerButton"
init-method="init">
<property name="actionListener">
<ref bean="addNewButtonActionListener"/>
</property>
<property name="text">
<value>Add New</value>
</property>
</bean> -->
<!-- <bean id="addNewButtonActionListener"
class="todo.ui.button.AddNewButtonActionListener">
<property name="list">
<ref bean="itemList"/>
</property>
<property name="table">
<ref bean="itemTable"/>
</property>
</bean> -->
<util:list id="itemList">
<value>Item 1</value>
<value>Item 2</value>
<value>Item 3</value>
</util:list>
</beans>
И я пытаюсь создать deleteButton
и addNewButton
бины вручную, в коде:
String[] contextPaths = new String[] {"todo/app-context.xml"};
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(contextPaths);
ActionListenerButton addNewButton = new ActionListenerButton();
addNewButton.setText("Add New");
System.out.println("setText(Add New)");
ListTableActionListener addActionListener = (ListTableActionListener) ctx.getBean("addNewButtonActionListener");
addNewButton.setActionListener(addActionListener);
ActionListenerButton deleteButton = new ActionListenerButton();
deleteButton.setText("Delete");
System.out.println("setText(Delete)");
ActionListener deleteActionListener = (ActionListener) ctx.getBean("deleteButtonActionListener");
deleteButton.setActionListener(deleteActionListener);
AutowireCapableBeanFactory factory = ctx.getAutowireCapableBeanFactory();
factory.autowireBean(addNewButton);
factory.initializeBean(addNewButton, "addNewButton");
factory.autowireBean(deleteButton);
factory.initializeBean(deleteButton, "deleteButton");
ctx.getBean("mainFrame");
Бины addNewButtonActionListener
и addNewButtonActionListener
, от которых зависят beanButton
и addNewButton
, определяются с помощью аннотаций:
@Component("addNewButtonActionListener")
public class AddNewButtonActionListener extends ListTableActionListener {
@Resource(name="itemList")
public void setList(List list) {
this.list = list;
}
@Resource(name="itemTable")
public void setTable(JTable itemTable) {
this.itemTable = itemTable;
}
public void actionPerformed(ActionEvent e) {
list.add("New Item");
itemTable.revalidate();
}
}
@Component("deleteButtonActionListener")
public class DeleteButtonActionListener extends ListTableActionListener {
@Resource(name="itemList")
public void setList(List list) {
this.list = list;
}
@Resource(name="itemTable")
public void setTable(JTable itemTable) {
this.itemTable = itemTable;
}
public void actionPerformed(ActionEvent e) {
int selectedRow = itemTable.getSelectedRow();
if (selectedRow == -1) {
// if there is no selected row, don't do anything
return;
}
if (itemTable.isEditing()) {
// if we are editing the table, don't do anything
return;
}
if (selectedRow < list.size()) {
list.remove(selectedRow);
itemTable.revalidate();
}
}
}
И класс ActionListenerButton
выглядит следующим образом:
public class ActionListenerButton extends JButton {
String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
private ActionListener actionListener;
public void setActionListener(ActionListener actionListener) {
this.actionListener = actionListener;
}
public ActionListener getActionListener() {
return actionListener;
}
public void init() {
this.addActionListener(actionListener);
}
}
Но при запуске приложения я получаю NoSuchBeanDefinitionException
с описанием "No bean named 'deleteButton' available":
14:04:49.677 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'itemScrollPane'
14:04:49.677 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'itemScrollPane'
14:04:49.680 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'itemTable'
14:04:49.701 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'itemScrollPane' to allow for resolving potential circular references
14:04:49.708 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'itemScrollPane'
14:04:49.708 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'itemTable'
14:04:49.708 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'itemList'
14:04:49.709 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
14:04:49.779 [main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@6eda5c9]
14:04:49.780 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:04:49.783 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
setText(Add New)
14:04:49.785 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'addNewButtonActionListener'
setText(Delete)
14:04:49.786 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'deleteButtonActionListener'
14:04:49.812 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mainFrame'
14:04:49.812 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'mainFrame'
14:04:49.828 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'mainFrame' to allow for resolving potential circular references
14:04:49.846 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'mainPanel'
14:04:49.846 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'mainPanel'
14:04:49.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'mainPanel' to allow for resolving potential circular references
14:04:49.869 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'itemScrollPane'
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainFrame' defined in class path resource [todo/app-context.xml]: Cannot resolve reference to bean 'mainPanel' while setting bean property 'mainPanel'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mainPanel' defined in class path resource [todo/app-context.xml]: Cannot resolve reference to bean 'buttonPanel' while setting bean property 'panelComponents' with key [1]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'deleteButton' available
Насколько я понимаю, вышеописанный код:
ActionListenerButton addNewButton = new ActionListenerButton();
addNewButton.setText("Add New");
System.out.println("setText(Add New)");
ListTableActionListener addActionListener = (ListTableActionListener) ctx.getBean("addNewButtonActionListener");
addNewButton.setActionListener(addActionListener);
ActionListenerButton deleteButton = new ActionListenerButton();
deleteButton.setText("Delete");
System.out.println("setText(Delete)");
ActionListener deleteActionListener = (ActionListener) ctx.getBean("deleteButtonActionListener");
deleteButton.setActionListener(deleteActionListener);
AutowireCapableBeanFactory factory = ctx.getAutowireCapableBeanFactory();
factory.autowireBean(addNewButton);
factory.initializeBean(addNewButton, "addNewButton");
factory.autowireBean(deleteButton);
factory.initializeBean(deleteButton, "deleteButton");
возвращает созданные с помощью аннотаций экземпляры бинов addNewButtonActionListener
и deleteButtonActionListener
, но при этом не создаёт экземпляров бинов addNewButton
и deleteButton
. Как можно создать эти бины программно (или через аннотации), без определения их в xml, и добавить их в контейнер Spring? Можно ли это вообще сделать с помощью AutowireCapableBeanFactory
?
Я нашла ответ на свой вопрос в вопросе SO. После изменения кода на:
AutowireCapableBeanFactory factory = ctx.getAutowireCapableBeanFactory();
BeanDefinition definition = new RootBeanDefinition(ActionListenerButton.class);
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
registry.registerBeanDefinition("addNewButton", definition);
registry.registerBeanDefinition("deleteButton", definition);
factory.initializeBean(addNewButton, "addNewButton");
factory.initializeBean(deleteButton, "deleteButton");
приложение запустилось.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Сейчас мои класс с тестами выглядит примерно такТо есть браузер запускается снова и снова для каждого теста Можно ли как-то сделать так, что...
Скачал готовый качественный Maven-проект с github'а, удалось его запустить, но Tomcat относительно всех адресов отдает 404
Обычно, когда новичкам рассказывают про преимущества Java, упоминают платформонезависимостьЯ правильно понял, что разработав Java-приложение,...
Делаю некую задачу, после отправки POST запроса приходит ответ, его я сохраняю в String-е и дальше хочу сохранить в PDF(результат POST запроса PDF файл)