Глава 02. Причудливая регистрация и получение Spring IoC Container Bean
Fancy a: Получить Bean по типу Bean
Конфигурационный файл beans.xml остается без изменений, а в ContainerTest добавляется новый метод.
// 通过bean类型获取bean
@Test
public void testGetBeanByClass(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
Person stark = context.getBean(Person.class);
System.out.println(stark);
}
Файл конфигурации beans.xml добавляет новую конфигурацию тега компонента.
<bean id="parker" class="com.citi.entity.Person">
<property name="lastName" value="Parker" />
<property name="age" value="18" />
<property name="gender" value="male" />
<property name="email" value="peterparker@gmail.com" />
</bean>
Выполните testGetBeanByClass() еще раз, и появится следующая ошибка:
No qualifying bean of type 'com.citi.entity.Person' available: expected single matching bean but found 2: stark,parker
Это связано с тем, что в конфигурационном файле есть несколько конфигураций bean-компонента.При получении bean-компонента не указано, какой bean-компонент получить, поэтому будет сообщено об ошибке.Modify testGetBeanByClass()
// 通过bean类型获取bean
@Test
public void testGetBeanByClass(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
Person stark = context.getBean("stark",Person.class);
System.out.println(stark);
}
Вывод выглядит следующим образом
Fancy 2: получить Bean через конструктор
В класс сущностей Person добавлен конструктор параметров.
public Person(String lastName, Integer age, String gender, String email) {
System.out.println("有参构造方法被调用");
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.email = email;
}
Зарегистрируйте все конфигурации тегов bean-компонентов в файле beans.xml и добавьте следующие теги bean-компонентов.
<bean id="parker" class="com.citi.entity.Person">
<constructor-arg name="lastName" value="Parker" />
<constructor-arg name="age" value="18" />
<constructor-arg name="gender" value="male" />
<constructor-arg name="email" value="peterparker@gmail.com" />
</bean>
Получить бобы в ContainerTest
@Test
public void testGetBeanByConstructor(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
Person parker = context.getBean("parker",Person.class);
System.out.println(parker);
}
Выполните testGetBeanByConstructor, консоль выведет результат следующим образом
Второй метод регистрации bean.xml при получении bean-компонентов через Constructor
<bean id="parker" class="com.citi.entity.Person">
<constructor-arg value="Parker" />
<constructor-arg value="18" />
<constructor-arg value="male" />
<constructor-arg value="peterparker@gmail.com" />
</bean>
Тег имени можно опустить, но порядок должен соответствовать порядку атрибутов в конструкторе.Вы также можете добавить атрибут индекса, чтобы сохранить согласованность атрибутов значения и класса, а индекс начинается с 0.
<bean id="parker" class="com.citi.entity.Person">
<constructor-arg value="Parker" index="0"/>
<constructor-arg value="18" index="1"/>
<constructor-arg value="male" index="2"/>
<constructor-arg value="peterparker@gmail.com" index="3"/>
</bean>
В случае перегрузки параметров вы можете использовать тип для выполнения типа значения атрибута.
Причудливые три: право назначать различные атрибуты
Добавьте новый класс сущностей Car, Book
public class Car {
private String carName;
private Integer price;
private String color;
// 此处省略getter/setter/toString方法
}
public class Book {
private String bookName;
private String author;
// 此处省略getter/setter/toString方法
}
Добавьте свойства в класс сущностей Person
public class Person {
private String lastName;
private Integer age;
private String gender;
private String email;
// 为各种属性正确赋值
private Car car;
private List<Book> bookList;
private Map<String,Object> map;
private Properties properties;
//无参构造方法
public Person() {
System.out.println("无参构造方法被调用");
}
public Person(String lastName, Integer age, String gender, String email) {
System.out.println("有参构造方法被调用");
this.lastName = lastName;
this.age = age;
this.gender = gender;
this.email = email;
}
// 此处省略getter/setter/toString方法
}
Создайте новый файл конфигурации bean-компонента assgin_value.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
Создайте новый тестовый класс AssignValueTest в тестовом каталоге.
public class AssignValueTest {
}
Если свойству не присвоено значение, базовый тип данных является значением по умолчанию, а ссылочный тип данных — null.В ansing_value.xml Увеличьте тег бобов
<!--不赋值,默认为Null-->
<bean id="stark" class="com.citi.entity.Person">
</bean>
Добавить тестовый код на CAnsValuetest Test Class
@Test
public void testAssignNull(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark = context.getBean(Person.class);
System.out.println(stark);
}
Выполните тестовый метод testAssignNull(), все свойства равны нулю
Если вы хотите присвоить значение null атрибуту, возьмите в качестве примера lastName, измените файл конфигурации xml
<!--不赋值,默认为Null-->
<bean id="stark" class="com.citi.entity.Person">
<property name="lastName">
<null/>
</property>
</bean>
Измените тестовый класс и добавьте, чтобы определить, является ли lastName нулевым.
@Test
public void testAssignNull(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark = context.getBean(Person.class);
System.out.println(stark.getLastName() == null);
System.out.println(stark);
}
Вывод консоли имеет значение true, указывающее на то, что присвоение значения NULL выполнено успешно. Чтобы присвоить значение NULL свойству, используйте метку
это значение, внешнее по отношению к приложениюДобавьте конфигурацию класса сущности Car в файл конфигурации xml, добавьте конфигурацию тега bean-компонента сущности Person и присвойте значение атрибуту Car.
<bean id="JAGUAR" class="com.citi.entity.Car">
<property name="carName" value="JAGUAR"></property>
<property name="color" value="英国绿"></property>
<property name="price" value="580000"></property>
</bean>
<!--引用外部的值-->
<bean id="stark01" class="com.citi.entity.Person">
<property name="car" ref="JAGUAR"></property>
</bean>
Добавлен тестовый метод testRefOutsideValue()
@Test
public void testRefOutsideValue(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Car car = context.getBean(Car.class);
Person stark01 = context.getBean("stark01",Person.class);
System.out.println(stark01.getCar() == car);
System.out.println(stark01);
System.out.println(car);
}
Выполните этот метод, тег ref используется в конфигурации xml для ссылки на конфигурацию Car, которая существует в контейнере, поэтому Car in the container и Car in Person совпадают.
Ссылка на внутреннюю ценностьДобавить xml-конфигурацию бина
<!--引用内部的值-->
<bean id="stark02" class="com.citi.entity.Person">
<property name="car">
<bean class="com.citi.entity.Car">
<property name="carName" value="Model 3"></property>
<property name="price" value="265652"></property>
<property name="color" value="black"></property>
</bean>
</property>
</bean>
добавить метод тестирования
@Test
public void testInsideValue(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Car car = context.getBean(Car.class);
Person stark02 = context.getBean("stark02",Person.class);
System.out.println(stark02.getCar() == car);
System.out.println(stark02);
System.out.println(car);
}
Автомобиль в контейнере по-прежнему является JAGUAR, в то время как автомобиль в человеке определяется как модель 3, они не совпадают, выведите false, используйте внутреннее значение и установите тег Bean в теге свойства.
Назначение свойства спискаКонфигурация XML увеличивается, определение тега bean-компонента BookList для справки, если список ссылок с метками ref
<bean id="PythonBook" class="com.citi.entity.Book">
<property name="bookName" value="Python21天跑路"></property>
<property name="author" value="佚名"></property>
</bean>
<!--List属性赋值-->
<bean id="stark03" class="com.citi.entity.Person">
<property name="bookList">
<list>
<bean id="book01" class="com.citi.entity.Book">
<property name="bookName" value="Java从入门到跑路"></property>
<property name="author" value="佚名"></property>
</bean>
<!--引用外部-->
<ref bean="PythonBook"></ref>
</list>
</property>
</bean>
добавить метод тестирования
@Test
public void testAssign2List(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Book pythonBook = context.getBean(Book.class);
Person stark03 = context.getBean("stark03",Person.class);
List<Book> bookList = stark03.getBookList();
for (Book book : bookList) {
System.out.println(book);
}
System.out.println(stark03);
System.out.println(pythonBook);
}
Выполнить тест, вывод в консоль
Попробуйте получить другую книгу в свойстве Person bookList, добавьте код в тестовый метод
Book book01 = context.getBean("book01",Book.class);
System.out.println(book01);
Выполнение тестового метода сообщает об ошибке, указывающей, что bean-компоненты внутри тега bean-компонента не могут быть напрямую получены контейнером, и только bean-компоненты, определенные в самом внешнем слое, могут быть непосредственно получены контейнером.
Назначение свойства картыДобавить конфигурацию xml, присвоить значение атрибуту карты, необходимо использовать тег ввода, определить ключ и карту в структуре карты с помощью тега ключа и значения, а также использовать key-ref и value-ref для ссылки на внешний ключ и значение, на карте вы можете использовать карту повторного вложения входа через вход
<!--Map属性赋值-->
<bean id="stark04" class="com.citi.entity.Person">
<property name="map">
<map>
<!--key,value,一个entry代表一个简直对-->
<entry key="name" value="Peter"></entry>
<entry key="book" value-ref="PythonBook"></entry>
<entry key="car">
<bean class="com.citi.entity.Car">
<property name="carName" value="Model Y"></property>
</bean>
</entry>
<entry key="mapKey">
<map>
<entry key="key01" value="value01"></entry>
</map>
</entry>
</map>
</property>
</bean>
Добавить метод тестирования
@Test
public void testAssign2Map(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark04 = context.getBean("stark04",Person.class);
Map<String, Object> map = stark04.getMap();
for (String key : map.keySet()) {
System.out.println("key:" + key);
}
for (Object value : map.values()) {
System.out.println("value:" + value);
}
System.out.println(stark04);
}
Выполните тестовый метод, консоль успешно распечатает структуру данных карты.
Назначение свойств свойстваДобавьте конфигурацию xml и используйте тег props, чтобы присвоить значение свойству Properties. Тег prop представляет каждую строку пары "ключ-значение" в файле конфигурации свойств.
<!--Properties属性赋值-->
<bean id="stark05" class="com.citi.entity.Person">
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">12345</prop>
</props>
</property>
</bean>
добавить метод тестирования
@Test
public void testAssign2Properties(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark05 = context.getBean("stark05",Person.class);
System.out.println(stark05);
}
Выполните тестовый метод, и консоль успешно выведет содержимое свойств.
пространство именПространства имен используются для предотвращения дублирования меток путем добавления префиксов (пространств имен), чтобы различать метки с одинаковыми именами, например
<car>
<name>F-TYPE</name>
<price>580000</price>
<owner>
<name>Stark</name>
<age>40</age>
</owner>
</car>
Имя под автомобилем и имя под владельцем дублируются.В это время необходимо различать добавлением префикса, то есть пространства имен, и изменить данные формата xml к следующему виду
<car>
<c:name>F-TYPE</c:name>
<price>580000</price>
<owner>
<o:name>Stark</o:name>
<age>40</age>
</owner>
</car>
В самом конфигурационном файле Spring есть пространство имен по умолчанию, то есть в заголовке
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd"
Представляет пространство имен по умолчанию, нет необходимости добавлять префикс
Использование пользовательского пространства имен необходимо импортировать и поместить в заголовок
xmlns:p = "http://www.springframework.org/schema/p"
Будет много советов при использовании
Добавить конфигурацию, используя префикс в xml
<bean id="stark06" class="com.citi.entity.Person" p:lastName="stark06">
</bean>
добавить метод тестирования
@Test
public void testAssignByNamespace(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark06 = context.getBean("stark06",Person.class);
System.out.println(stark06);
}
Консоль успешно выводит, что lastName — stark06 Используйте пространство имен util для присвоения значений свойствам карты
Сначала импортируйте пространство имен и измените заголовок на
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p = "http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.3.xsd">
</beans>
Затем используйте пространство имен util для создания карты с идентификатором mapSample для ссылки по тегу компонента с идентификатором stark07.
<util:map id="mapSample">
<!--key,value,一个entry代表一个简直对-->
<entry key="name" value="Thor"></entry>
<entry key="book" value-ref="PythonBook"></entry>
<entry key="car">
<bean class="com.citi.entity.Car">
<property name="carName" value="Model Y"></property>
</bean>
</entry>
</util:map>
<!--引用util名称空间为Map属性赋值-->
<bean id="stark07" class="com.citi.entity.Person">
<property name="map" ref="mapSample">
</property>
</bean>
добавить метод тестирования
@Test
public void testAssignMapByUtilNamespace(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark07 = context.getBean("stark07",Person.class);
System.out.println(stark07);
}
Журнал консоли показывает, что назначение выполнено успешно
Используйте пространство имен util для присвоения значений свойству ListДобавьте конфигурацию util: list в xml и добавьте тег bean-компонента для ссылки на тег списка util.
<util:list id="listSample">
<bean id="book02" class="com.citi.entity.Book">
<property name="bookName" value="Java从入门到跑路"></property>
<property name="author" value="佚名"></property>
</bean>
<!--引用外部-->
<ref bean="PythonBook"></ref>
</util:list>
<!--引用util名称空间为List属性赋值-->
<bean id="stark08" class="com.citi.entity.Person">
<property name="bookList" ref="listSample">
</property>
</bean>
добавить метод тестирования
@Test
public void testAssignListByUtilNamespace(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark08 = context.getBean("stark08",Person.class);
System.out.println(stark08);
}
Консоль показывает, что список был успешно назначен
Каскадное присвоение свойствPerson имеет атрибут Car, а атрибут Car имеет атрибут carName.Со стороны Person carName является каскадным атрибутом, то есть атрибутом атрибута. Добавить xml-конфигурацию
<!--级联属性赋值-->
<bean id="stark09" class="com.citi.entity.Person">
<property name="car" ref="JAGUAR"></property>
<!--修改引用的Car的价格-->
<property name="car.price" value="400000"></property>
</bean>
добавить тестовый код
@Test
public void testAssignCascadeProperty(){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:assign_value.xml");
Person stark09 = context.getBean("stark09",Person.class);
Car car = context.getBean(Car.class);
System.out.println(stark09);
System.out.println(car);
}
В журнале консоли видно, что цена была успешно изменена, с исходных 580000 до 400000, а также изменена цена оригинального автомобиля в контейнере.