Это первый день моего участия в августовском испытании обновлений, подробности о мероприятии:Испытание августовского обновления
1. Фабричный шаблон проектирования
1.1 Традиционные контейнеры — недостатки EJB
EJB (Enterprise Java Beans), известный как Enterprise Java Beans. Он контейнер, используемый предыдущим поколением. Давайте взглянем на традиционную систему J2EE.
Недостатки EJB фатальные:
- Суровая операционная среда.
- Переносимость кода плохая.
- EJB — это тяжеловесные фреймворки.
1.2 Что такое весна
Spring — это облегченное решение JavaEE, которое объединяет множество отличных шаблонов проектирования, наиболее важным из которых является шаблон проектирования factory. Он также содержит другие шаблоны проектирования, такие как: шаблон проектирования прокси, шаблон проектирования шаблона, шаблон проектирования стратегии и так далее.
1.3, что такое заводской шаблон проектирования
При традиционном способе создания объектов мы все вызываем конструктор без аргументов для создания объекта, то есть новый способ его создания, так что степень связи способа создания объекта (заданная как сильная связь между кодами, изменения в одной стороне повлияют на другую сторону) очень высока. ,
Как только нам нужно изменить тип, нам нужно изменить его в коде, перекомпилировать и развернуть.
1.4 Реализация фабричного шаблона проектирования
package com.factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class BeanFactory {
private static Properties env = new Properties();
static{
try {
//第一步 获得IO输入流
InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
//第二步 文件内容 封装 Properties集合中 key = userService ,value = com.service.impl.UserServiceImpl
env.load(inputStream);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*
对象的创建的两种方式:
1. 直接调用构造方法创建对象 UserService userService = new UserServiceImpl();
2. 通过反射的形式创建对象可以解耦合
Class clazz = Class.forName("com.service.impl.UserServiceImpl");
UserService userService = (UserService)clazz.newInstance();
*/
public static UserService getUserService() {
UserService userService = null;
try {
Class clazz = Class.forName(env.getProperty("userService"));
userService = (UserService) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return userService;
}
public static UserDAO getUserDAO(){
UserDAO userDAO = null;
try {
Class clazz = Class.forName(env.getProperty("userDAO"));
userDAO = (UserDAO) clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return userDAO;
}
}
userDAO = com.dao.userDAO
userService = com.service.userService
1.5 Модификация кода простой фабрики
Мы можем обнаружить, что код вышеперечисленного заводского дизайна является вонючий и длинный. Каждый раз, когда мы создаем новый объект, нам нужно переписать заводский класс, а большая часть кода одинакова, только созданные объекты разные , Итак, мы можем извлечь общий код для формирования общего заводского класса.
public class BeanFactory{
public static Object getBean(String key){
Object ret = null;
try {
Class clazz = Class.forName(env.getProperty(key));
ret = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
}
1.6. Резюме
Spring по сути фабрика, но мы не используем написанную нами фабрику в нашей повседневной разработке, потому что у этой фабрики мало функций и низкая производительность. фиксированный файл конфигурации (applicationContext.xml).
2. Начало работы с Spring
2.1 Введение в Spring
Spring — это облегченная среда разработки Java, появившаяся в 2003 году. Она была создана для решения сложностей разработки корпоративных приложений. В основе Spring лежит инверсия управления (IoC) и аспектно-ориентированное программирование (AOP). Spring — это легкая платформа с открытым исходным кодом, которую можно использовать в Java SE/EE.
Основная функция Spring — «разъединить» код и уменьшить связь между кодами. Это чтобы отношения между объектами и объектами (модулями и модулями) не ассоциировались с кодом, а объяснялись конфигурацией. То есть связь между объектами (модулями) описывается в Spring.
Spring использует Ioc для уменьшения связи между бизнес-объектами в соответствии с функциональными характеристиками кода. IoC избавляет основной бизнес от необходимости самостоятельно поддерживать отношения в процессе обращения друг к другу, то есть больше не нужно создавать объекты, которые будут использоваться. Вместо этого он единообразно управляется контейнером Spring, который автоматически «внедряется», а внедрение — это присваивание. АОП обеспечивает максимальное повторное использование сервисов системного уровня, и программистам больше не нужно вручную «смешивать» сервисы системного уровня с основной бизнес-логикой, а «сплетать» их унифицированным образом с помощью контейнера Spring.
2.2, преимущества Spring
Spring — это фреймворк, полуфабрикат. Состоит из 20 модулей. Это объект, управляемый контейнером. Контейнер содержит вещи. Контейнер Spring не содержит текста и чисел. Загружен предметами. Spring — это контейнер для хранения объектов. Его преимущества заключаются в основном в следующих аспектах.
- Легкий.
- Интерфейсно-ориентированное программирование.
- Аспектно-ориентированное программирование
- Другие отличные фреймворки могут быть легко интегрированы.
2.2.1 Легкий
JAR-файлы, используемые инфраструктурой Spring, относительно малы, как правило, менее 1M или сотен КБ. Общее количество jar-файлов, необходимых для основных функций Spring, составляет около 3M. Работа среды Spring требует меньше ресурсов и имеет высокую эффективность. Не зависит от других банок.
2.2.2 Интерфейсно-ориентированное программирование
Spring обеспечивает инверсию управления Ioc, контейнер управляет объектами и зависимостями объектов. Способ создания объекта в программном коде теперь делает контейнер.Развязка зависимостей между объектами.
2.2.3 Аспектно-ориентированное программирование (АОП)
Функция АОП, предоставляемая Spring, облегчает аспектно-ориентированное программирование, и многие функции, которые нелегко реализовать с помощью традиционного ООП, могут быть легко обработаны АОП. В Spring разработчики могут быть освобождены от сложных кодов управления транзакциями и гибко управлять транзакциями в декларативной манере, повышая эффективность и качество разработки.
2.2.4 Интеграция других отличных фреймворков
Spring не исключает различных отличных фреймворков с открытым исходным кодом, наоборот, Spring может уменьшить сложность использования различных фреймворков Spring обеспечивает прямую поддержку различных отличных фреймворков (таких как Shiro, MyBatis). Упростите использование фреймворков. Весна похожа на удлинитель, а другие рамки — это вилки, которые можно легко комбинировать вместе. Какую бы рамку ни нужно было использовать, вставьте эту вилку в удлинитель. Не нужно легко снимать.
2.3, Архитектура Spring
Spring состоит из более чем 20 модулей, которые можно разделить на доступ/интеграцию данных (Data Access/Integration), Web, аспектно-ориентированное программирование (AOP, Aspects), JVM-предоставляющий агент (Instrumentation), отправку сообщений (Messaging), основной контейнер (Core Container) и Тестовый (Test).
2.4, основной API Spring
Ядром Spring является большая фабрика: ApplicationContext, которая используется для создания объектов и может быть разделена.Это интерфейс, но ApplicationContext — это тяжеловесный фабричный объект, который занимает много памяти, поэтому мы не будем часто создавать объекты, как правило, приложение создает только фабричный объект. ApplicationContext является потокобезопасным, и к нему могут одновременно обращаться несколько потоков.
У него есть две реализации:
- Применимо к среде, отличной от WEB: ClassPathXmlApplication
- Применимо к веб-среде: XmlApplicationContext
2.5, случай Spring
2.5.1. Введение зависимостей
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.5.3, создать тип
package com.domain;
/**
* @author Xiao_Lin
* @date 2021/2/4 15:57
*/
public class Person {
}
2.5.4, изменить файл конфигурации
Измените конфигурацию в файле конфигурации applicationContext.xml.
<!-- id属性:名字-->
<!-- class属性:需要创建对象的全限定名-->
<bean id="person" class="com.domain.Person"/>
2.5.5 Создание объектов
/**
* 用于测试Spring的第一个程序
*/
@Test
public void testSpring(){
// 1. 获得Spring的工厂
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
// 2. 通过工厂类来获得对象
Person person = (Person)applicationContext.getBean("person");
System.out.println(person);
}
2.6, подробный анализ
2.6.1. Объяснение терминов
Объект, созданный фабрикой Spring, называется bean-компонентом или компонентом (компонентом).
2.6.2, связанные методы
//通过这种方式获得对象,就不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);
//当前Spring的配置文件中 只能有一个<bean>标签的class是Person类型
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);
//获取的是 Spring工厂配置文件中所有bean标签的id值 person person1
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
//根据类型获得Spring配置文件中对应的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {
System.out.println("id = " + id);
}
//用于判断是否存在指定id值的bean
if (ctx.containsBeanDefinition("a")) {
System.out.println("true = " + true);
}else{
System.out.println("false = " + false);
}
//用于判断是否存在指定id(name)值的bean
if (ctx.containsBean("person")) {
System.out.println("true = " + true);
}else{
System.out.println("false = " + false);
}
2.7 Простая схема создания объекта Spring
Примечание. Нижний уровень отражения вызывает конструктор без параметров для создания экземпляра объекта.Даже если конструктор является закрытым, его все равно можно вызвать для создания экземпляра объекта.
2.8. Внимание
В процессе дальнейшей разработки, по идее, все объекты передаются в фабрику Spring для создания, но есть особый вид объекта — объект сущности не будет передан в Spring для создания, он будет передан в слой сохраняемости для создания .
3. Инъекция
3.1 Что такое инъекция
Внедрение означает, что в процессе создания объекта Spring устанавливает свойства зависимости объекта для объекта посредством конфигурации.
3.2 Зачем нужно делать инъекции
Кодируя (setXxx), присваивайте значения переменным-членам, и возникает связь.
3.3, способ впрыска
- установить впрыск:Его класс должен предоставить соответствующий метод установки.
- Внедрение конструктора: используйте конструктор для внедрения.
3.4, установка впрыска
package com.domain;
/**
* @author Xiao_Lin
* @date 2021/2/4 15:57
*/
public class Person {
private String username;
private Integer password;
@Override
public String toString() {
return "Person{" +
"username='" + username + '\'' +
", password=" + password +
'}';
}
public Person(String username, Integer password) {
this.username = username;
this.password = password;
}
public Person() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getPassword() {
return password;
}
public void setPassword(Integer password) {
this.password = password;
}
}
<bean id="person" class="com.domain.Person">
<property name="username">
<value>Xiao_Lin</value>
</property>
<property name="password">
<value>123456</value>
</property>
</bean>
/**
* 用于测试注入
*/
@Test
public void testDI(){
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = application.getBean("person", Person.class);
System.out.println(person);
}
3.4.1. Принципиальная схема установки впрыска
Spring завершает назначение переменных-членов, вызывая метод set, соответствующий свойству объекта на нижнем уровне.
3.4.2. Подробное объяснение установки впрыска
Для различных типов переменных-членов мы не всегда можем использоватьvalue
Метки, нам нужно вложить другие метки, мы классифицируем возможные типы переменных-членов на две категории:
- Встроенные типы JDK.
- Пользовательский тип.
3.4.2.1, встроенные типы JDK
3.4.2.1.1, Базовые типы данных String+8
используются напрямуюvalue
Просто пометить
<property name="password">
<value>123456</value>
</property>
3.4.2.1.2, Тип массива
Для типов массива нам нужно использовать файл конфигурацииlist
Метка, указывающая, что это тип массива, вложенныйvalue
метка для присвоения.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String[] emails;
}
<property name="emails">
<list>
<value>124@qq.com</value>
<value>456@163.com</value>
</list>
</property>
3.4.2.1.3, Набор наборов
Для типа коллекции set нам нужно использовать файл конфигурации для использованияset
этикетка, указывающая, чтоset
Установите тип, вложите соответствующую метку в поле Установить универсальный тип для назначения.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Set<String> tels;
}
<property name="tels">
<set>
<value>123456</value>
<value>456789</value>
<value>13579</value>
</set>
</property>
Для набора наборов, поскольку мы стандартизировали общий тип как String, она имеет 8 основных типов данных, поэтому тег значения вложен в тег набора. Если общий тип не указан или указаны другие общие типы, необходимо проанализировать вложенные теги набора в соответствии с конкретной ситуацией.
3.4.2.1.4, Коллекция списков
Для типа коллекции List нам нужно использовать файл конфигурации для использованияlist
Метка указывает, что это тип коллекции List, и ему назначена соответствующая метка во вложенном универсальном типе List.
Какие теги вложены в примечание к списку, зависит от универсального типа в коллекции List.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private List<String> address;
}
<property name="address">
<list>
<value>sz</value>
<value>sz</value>
<value>gz</value>
</list>
</property>
3.4.2.1.5, Коллекция карт
Для коллекции Map существует внутренний класс Entry, поэтому метка, которую нам нужно использовать в файле конфигурации, должна использоватьmap
теги для вложенияentry
Тег, который инкапсулирует пару пар ключ-значение. Мы используемkey
метка для представления ключа,Метка, соответствующая вложенному ключу внутри, и значение должно выбирать соответствующую метку в соответствии с соответствующим типом.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Map<String,String> qq;
}
<property name="qq">
<map>
<entry>
<key><value>zs</value></key>
<value>123456</value>
</entry>
<entry>
<key><value>lisi</value></key>
<value>456789</value>
</entry>
</map>
</property>
3.4.2.1.6, Коллекция свойств
Свойства аналогичны специальной Карте, егоkey
а такжеvalue
должно бытьString
Типы.
В файле конфигурации мы используемprops
теги, вложенные внутрьprop
этикетка, аprop
является парой ключ-значение, ключ записывается вkey
В атрибутах значение записывается внутри тега.
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Properties properties;
}
<property name="properties">
<props>
<prop key="username">admin</prop>
<prop key="password">123456</prop>
</props>
</property>
3.4.2.2, пользовательский тип
3.4.2.2.1 Первый метод впрыска
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hobby {
private String name;
}
<property name="hobby">
<bean class="com.domain.Hobby"/>
</property>
Мы можем обнаружить, что первый метод впрыска на самом деле находится вproperty
написать тегbean
Этикетка, недостатки у него тоже очевидны:
- Код файла конфигурации избыточен: когда у меня есть 10 000 классов, которым нужно ссылаться на один и тот же объект, мне нужно написать один и тот же фрагмент кода 10 000 раз.
- Внедренный объект создается несколько раз, тратя впустую ресурсы памяти (JVM), потому что каждый раз, когда я пишу
bean
Метка означает создание нового объекта.
3.4.2.2.2, второй метод впрыска
Ввиду очевидных недостатков первого метода инъекции, нам необходимо его улучшить, поэтому у нас есть второй метод инъекции.Этот метод заключается в создании копии объекта, который нам нужно ввести заранее, и кому это нужно, может обратиться к это. .
<bean>
<property name="hobby">
<ref bean="hobby"/>
</property>
</bean>
<bean id="hobby" class="com.domain.Hobby">
<property name="name">
<value>admin</value>
</property>
</bean>
3.4.3 Упрощенное написание набора инъекций
3.4.3.1 Упрощение на основе атрибутов
Впрыск типа JDK
мы можем использоватьvalue
свойства для упрощенияvalue
Значение метки, но можно упростить только значение 8 основных типов данных ➕ Тип Stirng.
<!--以前的方式-->
<property name="name">
<value>Xiao_Lin</value>
</property>
<!--简化后的方式-->
<property name="name" value="Xiao_Lin"/>
Внедрение определяемого пользователем типа
Мы можем использовать атрибут ref для упрощенияref
Значение ярлыка.
<!--以前的方式-->
<property name="hobby">
<ref bean="hobby"/>
</property>
<!--简化后的方式-->
<property name="hobby" ref="hobby"/>
3.4.3.2 Упрощение на основе пространства имен p
мы можем узнать, что,bean
Многие значения тега повторяются и избыточны, поэтому можно использоватьp
Пространство имен для упрощения.
<!--内置数据类型-->
<bean id="person" class="com.domain.Person" p:username="zs" p:password="123456" />
<!--用户自定义类型-->
<bean id="hobbyBean" class="com.domain.Hobby"></bean>
<bean id="hobby" class="com.domain.Person" p:hobby-ref="hobbyBean"
3.5. Инъекция конструкции
Spring вызывает конструктор и присваивает значения переменным-членам через файл конфигурации.Если вы хотите использовать внедрение конструктора, вы должны предоставить конструктору параметры.
Теги, используемые для инъекции конструкции:constructor-arg
метка, параметр конструктора представляет собой паруconstructor-arg
Этикетка. Порядок и номер должны совпадать с параметрами конструктора.
Когда происходит перегрузка конструктора, мы можем управлятьconstructor-arg
номер для контроля. Если есть перегрузка с тем же количеством параметров конструктора (например, первый конструктор присваивает значение имени, а второй конструктор присваивает значение типу), нужно использоватьtype
атрибут для указания типа.
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Hobby {
private String name;
private String type;
}
<bean id="hobbyBean" class="com.domain.Hobby">
<constructor-arg>
<value>running</value>
</constructor-arg>
<constructor-arg>
<value>dayily</value>
</constructor-arg>
</bean>
/**
* 用于测试构造注入
*/
@Test
public void testDI2(){
ClassPathXmlApplicationContext cxt =
new ClassPathXmlApplicationContext("/applicationContext.xml");
Hobby hobbyBean = cxt.getBean("hobbyBean", Hobby.class);
System.out.println(hobbyBean);
}
3.6, сводка инъекций
4. Инверсия управления (IOC) и внедрение зависимостей (DI)
4.1 Инверсия управления (IOC)
Инверсия управления (IoC, Inversion of Control) — это концепция и идея. Относится к передаче контейнеру прав на вызов объекта, которые традиционно напрямую контролируются программным кодом, а сборка и управление объектами реализуются через контейнер. Инверсия управления — это передача управления объектом от самого программного кода внешнему контейнеру. Создавайте объекты, назначайте атрибуты и управляйте зависимостями через контейнеры.
Проще говоряИнверсия управления заключается в инвертировании (переносе) управления назначением переменных-членов из кода в фабрику Spring и файл конфигурации.
IoC — это концепция, идея, которую можно реализовать разными способами.Spring Framework реализует IoC с использованием внедрения зависимостей (DI).
4.2. Внедрение зависимостей (DI)
Зависимость: класс classA содержит экземпляр classB, и метод classB вызывается в classA для завершения функции, то есть classA имеет зависимость от classB.
Внедрение зависимостей: когда классу нужен другой класс, другой класс можно использовать в качестве переменной-члена этого класса и, наконец, внедрить (назначить) через файл конфигурации Spring. Проще говоря, это означает, что когда программа работает, если ей нужно вызвать другой объект для помощи, то не обязательно создавать вызываемый объект в коде, а полагаться на внешний контейнер, который создается внешним контейнером и передается к программе.
Внедрение зависимостей в Spring почти не предъявляет требований к вызывающей стороне и вызываемой стороне и полностью поддерживает управление зависимостями между объектами.
4.3. Резюме
Контейнер Spring — это суперфабрика, отвечающая за создание и управление всеми объектами Java, которые называются bean-компонентами. Контейнер Spring управляет зависимостями между bean-компонентами в контейнере, а Spring использует «внедрение зависимостей» для управления зависимостями между bean-компонентами. Используйте IoC для достижения развязки и развязки между объектами.