Систематические знания и вопросы для интервью по изучению Java, которые я обобщил сам, находятся в открытом доступе и в настоящее время имеют более 41 000 звезд. Он будет продолжать улучшаться, предложения и рекомендации приветствуются, и Star также приветствуется:GitHub.com/snail Climb/…
Какие шаблоны проектирования используются в JDK? Какие шаблоны проектирования используются в Spring? Эти два вопроса относительно часто встречаются на собеседованиях. Я искал в Интернете объяснения шаблонов проектирования в Spring, которые почти шаблонны, и большинство из них устарели. Итак, я потратил несколько дней на то, чтобы обобщить его сам, в силу моих ограниченных личных возможностей вы можете указать на любые ошибки в тексте. Кроме того, объем статьи ограничен, я затронул только интерпретацию шаблонов проектирования и некоторый исходный код. Основная цель этой статьи — обзор шаблонов проектирования в Spring.
Шаблоны проектирования представляют собой лучшие методы компьютерного программирования при разработке объектно-ориентированного программного обеспечения. Во фреймворке Spring широко используются различные типы шаблонов проектирования.Давайте посмотрим, какие существуют шаблоны проектирования?
Инверсия управления (IoC) и внедрение зависимостей (DI)
IoC (инверсия управления, переворот управления)Это очень, очень важная концепция Spring, это не технология, а разделяющая дизайнерская идея. Его основная цель — добиться развязки между объектами с зависимостями с помощью «третьих лиц» (контейнеров IOC в Spring) (IOC — это легко управлять объектами, их можно просто использовать), тем самым уменьшая связь между кодами.IOC — это принцип, а не шаблон, следующие шаблоны (но не ограничиваясь ими) реализуют принцип IoC.
Контейнер Spring IOC похож на фабрику: когда нам нужно создать объект, нам нужно только настроить файл конфигурации/аннотацию, не учитывая, как создается объект.Контейнер IOC отвечает за создание объектов, соединение объектов, настройку этих объектов и управление всем жизненным циклом этих объектов от создания до их полного уничтожения.
В реальном проекте, если класс службы имеет сотни или даже тысячи классов в качестве нижнего уровня, нам необходимо создать экземпляр службы.Возможно, вам придется каждый раз выяснять конструкторы всех базовых классов службы, что может поставить Народ сводит с ума. Если вы используете IOC, вам нужно только настроить его, а затем ссылаться на него там, где он вам нужен, что значительно повышает удобство сопровождения проекта и снижает сложность разработки. Для понимания Spring IOC рекомендуется прочитать ответ от Zhihu:Ууху. Call.com/question/23…,очень хороший.
Как вы понимаете контрольный переворный?Например: «Объект a зависит от объекта b. Когда объекту a нужно использовать объект b, он должен создать его сам. Но когда система вводит IOC-контейнер, прямая связь между объектом a и объектом b теряется. При этом time , когда объекту a необходимо использовать объект b, мы можем указать контейнер IOC для создания объекта b и внедрить его в объект a". Процесс получения объектом a зависимого объекта b меняется с активного поведения на пассивное, а управление меняется на противоположное, что является источником названия инверсии управления.
DI (внедрение зависимостей, внедрение зависимостей) — это шаблон проектирования для достижения инверсии управления.Внедрение зависимостей — это передача переменных экземпляра в объект.
Заводской шаблон проектирования
Spring использует заводской шаблон для передачиBeanFactory
илиApplicationContext
Создайте объект bean.
Сравните два:
-
BeanFactory
: отсроченная инъекция (вводится только при использовании бобов) по сравнению сBeanFactory
Другими словами, он будет занимать меньше памяти и программа будет запускаться быстрее. -
ApplicationContext
: Когда контейнер запускается, независимо от того, используете вы его или нет, создайте все компоненты сразу.BeanFactory
Предоставляет только самую базовую поддержку внедрения зависимостей,ApplicationContext
расширенныйBeanFactory
, за исключениемBeanFactory
В функции гораздо больше функций, поэтому общие разработчики используютApplicationContext
будет больше.
Три класса реализации ApplicationContext:
-
ClassPathXmlApplication
: обращаться с файлами контекста как с ресурсами пути к классам. -
FileSystemXmlApplication
: загрузить информацию об определении контекста из XML-файла в файловой системе. -
XmlWebApplicationContext
: загружать информацию об определении контекста из файла XML в веб-системе.
Example:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
"C:/work/IOC Containers/springframework.applicationcontext/src/main/resources/bean-factory-config.xml");
HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
obj.getMsg();
}
}
Режим дизайна одного дела
В нашей системе есть некоторые объекты, которые нам нужны только один, например: пул потоков, кеш, диалоговое окно, реестр, объект журнала, объекты, которые действуют как принтеры, видеокарты и другие драйверы устройств. На самом деле этот тип объекта может иметь только один экземпляр, и создание нескольких экземпляров может вызвать некоторые проблемы, такие как ненормальное поведение программы, чрезмерное использование ресурсов или противоречивые результаты.
Преимущества использования шаблона singleton:
- Для часто используемых объектов время, затрачиваемое на создание объектов, можно не учитывать, что является значительным накладным расходом системы для таких тяжеловесных объектов;
- Поскольку количество новых операций уменьшается, частота использования системной памяти также будет снижена, что снизит нагрузку на сборщик мусора и сократит время паузы сборщика мусора.
Областью действия bean-компонентов по умолчанию в Spring является singleton.Помимо одноэлементной области видимости, bean-компоненты в Spring имеют следующие области видимости:
- прототип: новый экземпляр компонента создается при каждом запросе.
- request : каждый HTTP-запрос будет генерировать новый bean-компонент, который действителен только в рамках текущего HTTP-запроса.
- session : каждый HTTP-запрос будет генерировать новый bean-компонент, который действителен только в рамках текущего HTTP-сеанса.
- global-session: глобальная область сеанса, имеющая смысл только в веб-приложениях на основе портлетов, больше недоступна в Spring 5. Портлеты — это небольшие веб-плагины Java, которые генерируют фрагменты семантического кода (например, HTML). Они основаны на контейнерах портлетов и могут обрабатывать HTTP-запросы, как сервлеты. Однако, в отличие от сервлетов, у каждого портлета свой сеанс.
Как Spring реализует синглтоны:
- xml :
<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
- аннотация:
@Scope(value = "singleton")
Весенний абонементConcurrentHashMap
Особый способ реализации одноэлементного реестра реализует одноэлементный шаблон. Основной код одноэлементной реализации Spring выглядит следующим образом.
// 通过 ConcurrentHashMap(线程安全) 实现单例注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//...省略了很多代码
try {
singletonObject = singletonFactory.getObject();
}
//...省略了很多代码
// 如果实例对象在不存在,我们注册到单例注册表中。
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//将对象添加到单例注册表
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
}
Конструкция прокси-сервера
Применение шаблона прокси в АОП
АОП (аспектно-ориентированное программирование: аспектно-ориентированное программирование) может сделать тех, кто не имеет отношения к бизнесу,Однако он инкапсулируется логикой или ответственностью (например, обработка транзакций, управление журналами, контроль разрешений и т. д.), обычно вызываемой бизнес-модулями.,легкоУменьшить дублирование кода в системе,Уменьшите связь между модулями,иХорошо для будущей масштабируемости и ремонтопригодности.
Spring AOP основан на динамическом прокси, если проксируемый объект реализует интерфейс, то Spring AOP будет использоватьJDK Proxy, для создания прокси-объекта и для объектов, которые не реализуют интерфейс, вы не можете использовать JDK Proxy для прокси.В настоящее время Spring AOP будет использоватьCglib, то Spring AOP будет использоватьCglibСоздайте подкласс проксируемого объекта в качестве прокси, как показано на следующем рисунке:
Конечно, вы также можете использовать AspectJ, Spring AOP интегрировал AspectJ, AspectJ следует рассматривать как наиболее полную структуру AOP в экосистеме Java.
После использования АОП мы можем абстрагировать некоторые общие функции и использовать их непосредственно там, где они нужны, что значительно упрощает объем кода. Это также удобно, когда нам нужно добавить новые функции, что также улучшает масштабируемость системы. АОП используется в таких сценариях, как функции регистрации и управления транзакциями.
В чем разница между Spring AOP и AspectJ AOP?
Spring AOP — это усовершенствование времени выполнения, а AspectJ — усовершенствование времени компиляции.Spring AOP основан на проксировании, а AspectJ основан на манипулировании байт-кодом.
Spring AOP интегрировал AspectJ, AspectJ следует рассматривать как наиболее полную структуру AOP в экосистеме Java. AspectJ более мощный, чем Spring AOP, но Spring AOP относительно проще.
Если у нас меньше граней, то между ними нет большой разницы в производительности. Однако, когда аспектов слишком много, лучше выбрать AspectJ, который намного быстрее, чем Spring AOP.
шаблонный метод
Шаблон шаблонного метода — это поведенческий шаблон проектирования, который определяет скелет алгоритма в операции, откладывая при этом некоторые шаги на подклассы. Шаблонные методы позволяют подклассам переопределять реализацию определенных шагов алгоритма без изменения его структуры.
public abstract class Template {
//这是我们的模板方法
public final void TemplateMethod(){
PrimitiveOperation1();
PrimitiveOperation2();
PrimitiveOperation3();
}
protected void PrimitiveOperation1(){
//当前类实现
}
//被子类实现的方法
protected abstract void PrimitiveOperation2();
protected abstract void PrimitiveOperation3();
}
public class TemplateImpl extends Template {
@Override
public void PrimitiveOperation2() {
//当前类实现
}
@Override
public void PrimitiveOperation3() {
//当前类实现
}
}
веснойjdbcTemplate
,hibernateTemplate
Для классов, которые работают с базой данных, которые заканчиваются на Template, они используют шаблон шаблона. В общем, мы используем наследование для реализации режима шаблона, но Spring не использует этот метод, а использует режим Callback для взаимодействия с режимом метода шаблона, что не только достигает эффекта повторного использования кода, но и повышает гибкость.
Шаблон наблюдателя
Паттерн Наблюдатель — это поведенческий паттерн объекта. Это означает, что существует зависимость между объектом и объектом, когда объект изменяется, объект, от которого объект зависит, также будет реагировать. Модель Spring, управляемая событиями, — это классическое применение шаблона наблюдателя. Модель Spring, управляемая событиями, очень полезна для разделения нашего кода во многих сценариях. Например, каждый раз, когда мы добавляем продукт, нам нужно снова обновлять индекс продукта, в это время мы можем использовать режим наблюдателя для решения этой проблемы.
Три роли в событийно-ориентированной модели Spring
роль события
ApplicationEvent
(org.springframework.context
package) действует как роль события, которая является абстрактным классом, наследующимjava.util.EventObject
и понялjava.io.Serializable
интерфейс.
Следующие события существуют по умолчанию в Spring, и все они верныApplicationContextEvent
реализация (унаследована отApplicationContextEvent
):
-
ContextStartedEvent
:ApplicationContext
События, запускаемые после запуска; -
ContextStoppedEvent
:ApplicationContext
Событие запускается после остановки; -
ContextRefreshedEvent
:ApplicationContext
Событие запускается после завершения инициализации или обновления; -
ContextClosedEvent
:ApplicationContext
Событие запускается после выключения.
роль прослушивателя событий
ApplicationListener
Действуя как прослушиватель событий, это интерфейс, который определяет только одинonApplicationEvent()
метод обработкиApplicationEvent
.ApplicationListener
Исходный код класса интерфейса выглядит следующим образом, видно, что определение интерфейса показывает, что события в интерфейсе нужно только реализоватьApplicationEvent
Вот и все. Итак, в Spring нам просто нужно реализоватьApplicationListener
реализация интерфейсаonApplicationEvent()
способ завершения события мониторинга
package org.springframework.context;
import java.util.EventListener;
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
Роль издателя события
ApplicationEventPublisher
Выступая в качестве издателя событий, он также является интерфейсом.
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
ApplicationEventPublisher
интерфейсpublishEvent()
Этот методAbstractApplicationContext
Класс реализован, почитайте реализацию этого метода, вы обнаружите, что событие на самом деле передается черезApplicationEventMulticaster
транслировать. Слишком много специфического контента, поэтому я не буду его здесь анализировать, а возможно напишу отдельную статью, чтобы упомянуть об этом позже.
Сводка потока событий Spring
- Определить событие: реализовать событие, которое наследуется от
ApplicationEvent
и написать соответствующий конструктор; - Определение прослушивателя событий: реализация
ApplicationListener
интерфейс, переопределениеonApplicationEvent()
метод; - Публиковать сообщения с помощью издателей событий: можно сделать через
ApplicationEventPublisher
изpublishEvent()
способ публикации сообщения.
Example:
// 定义一个事件,继承自ApplicationEvent并且写相应的构造函数
public class DemoEvent extends ApplicationEvent{
private static final long serialVersionUID = 1L;
private String message;
public DemoEvent(Object source,String message){
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
// 定义一个事件监听者,实现ApplicationListener接口,重写 onApplicationEvent() 方法;
@Component
public class DemoListener implements ApplicationListener<DemoEvent>{
//使用onApplicationEvent接收消息
@Override
public void onApplicationEvent(DemoEvent event) {
String msg = event.getMessage();
System.out.println("接收到的信息是:"+msg);
}
}
// 发布事件,可以通过ApplicationEventPublisher 的 publishEvent() 方法发布消息。
@Component
public class DemoPublisher {
@Autowired
ApplicationContext applicationContext;
public void publish(String message){
//发布事件
applicationContext.publishEvent(new DemoEvent(this, message));
}
}
при звонкеDemoPublisher
изpublish()
метод, такой какdemoPublisher.publish("你好")
, консоль напечатает:接收到的信息是:你好
.
режим адаптера
Шаблон адаптера (Adapter Pattern) преобразует интерфейс в другой интерфейс, который хочет клиент. Шаблон адаптера позволяет этим классам с несовместимыми интерфейсами работать вместе, и его псевдоним — Wrapper.
Шаблон адаптера в Spring AOP
Мы знаем, что реализация Spring AOP основана на режиме прокси, но расширение или совет (Advice) Spring AOP использует режим адаптера, а соответствующий интерфейсAdvisorAdapter
. Распространенные типы советов:BeforeAdvice
(перед вызовом целевого метода предварительное уведомление),AfterAdvice
(После вызова целевого метода отправьте уведомление),AfterReturningAdvice
(после выполнения целевого метода, перед возвратом) и так далее. Каждому типу Advice (уведомления) соответствует свой перехватчик:MethodBeforeAdviceInterceptor
,AfterReturningAdviceAdapter
,AfterReturningAdviceInterceptor
. Предопределенные уведомления Spring должны быть адаптированы кMethodInterceptor
Объект интерфейса типа (перехватчик метода) (например:MethodBeforeAdviceInterceptor
Ответственный за адаптациюMethodBeforeAdvice
).
Шаблон адаптера весной MVC
В Spring MVC,DispatcherServlet
Звонил по запросу информацииHandlerMapping
, который анализирует запрос, соответствующийHandler
. принять соответствующиеHandler
(Это то, что мы обычно говоримController
контроллер), начните сHandlerAdapter
Работа с адаптером.HandlerAdapter
В качестве ожидаемого интерфейса для адаптации целевого класса используется конкретный класс реализации адаптера.Controller
Как класс, который нужно адаптировать.
Зачем использовать шаблон адаптера в Spring MVC?весной MVCController
много видов, разные видыController
Запросы обрабатываются по-разному. Если вы не используете режим адаптера,DispatcherServlet
Получить соответствующий тип напрямуюController
, вам нужно судить самостоятельно, например, следующий код:
if(mappedHandler.getHandler() instanceof MultiActionController){
((MultiActionController)mappedHandler.getHandler()).xxx
}else if(mappedHandler.getHandler() instanceof XXX){
...
}else if(...){
...
}
Если мы добавим ещеController
Тип должен добавить еще одну строку суждения к приведенному выше коду.Такая форма усложняет поддержку программы и нарушает принцип открытости-закрытости в шаблоне проектирования - открыт для расширения и закрыт для модификации.
шаблон декоратора
Шаблон декоратора может динамически добавлять к объекту некоторые дополнительные свойства или поведение. Шаблон декоратора более гибок, чем использование наследования. Проще говоря, когда нам нужно изменить исходную функцию, но мы не хотим изменять исходный код напрямую, создайте декоратор вне исходного кода. На самом деле в JDK есть много мест, где используется шаблон декоратора, напримерInputStream
семья,InputStream
под классFileInputStream
(прочитать файл),BufferedInputStream
(увеличьте кеш, чтобы значительно улучшить скорость чтения файлов) и другие подклассы не измененыInputStream
код для расширения его функциональности.
При настройке DataSource в Spring DataSource могут быть разные базы данных и источники данных. Можем ли мы динамически переключаться между различными источниками данных в соответствии с потребностями клиентов, не изменяя код исходного класса? В настоящее время используется шаблон декоратора (на данный момент я не совсем понимаю конкретный принцип). Шаблон оболочки, используемый в Spring, содержит имя классаWrapper
илиDecorator
. Эти классы в основном динамически добавляют некоторые дополнительные обязанности к объекту.
Суммировать
Какие шаблоны проектирования используются в среде Spring?
-
Заводской шаблон проектирования: Spring использует заводской шаблон через
BeanFactory
,ApplicationContext
Создайте объект bean. - Шаблон проектирования прокси: Реализация функциональности Spring AOP.
- одноэлементный шаблон проектирования: Bean-компоненты в Spring по умолчанию являются синглтонами.
-
Шаблон метода шаблона: весной
jdbcTemplate
,hibernateTemplate
Для классов, которые работают с базой данных, которые заканчиваются на Template, они используют шаблон шаблона. - шаблон оформления обертки: Наш проект должен подключаться к нескольким базам данных, и разные клиенты будут получать доступ к разным базам данных в соответствии со своими потребностями при каждом посещении. Этот режим позволяет нам динамически переключаться между различными источниками данных в соответствии с потребностями клиента.
- Шаблон наблюдателя:Модель Spring, управляемая событиями, — это классическое применение шаблона наблюдателя.
-
режим адаптера: Улучшение или совет Spring AOP использует режим адаптера, а адаптация режима адаптера также используется в Spring MVC.
Controller
. - ......
Ссылаться на
- "Инсайдер технологии Spring"
- блог Quota Oh You Learn.com/Java-pro и RA…
- блог.Также Армин.top/2018/03/27/…
- woohoo.tutorials Teacher.com/IOC/Я, четвертая дочь…
- design-patterns.read the doc S.IO/this_cn/latshan…
- nuggets.capable/post/684490…
- nuggets.capable/post/684490…
публика
Если вы хотите следить за моими обновленными статьями и делиться галантерейными товарами в режиме реального времени, вы можете подписаться на мой официальный аккаунт.
«Нападение на Java-интервью»:"Java Interview Assault" V2.0 PDF-версия, полученная из этого документа для интервью.публикаФоновый ответ"Блиц-интервью по Java"Получите это бесплатно!
Важные учебные ресурсы для Java-инженеров:Некоторые Java-инженеры обычно используют ключевые слова для фонового ответа общедоступной учетной записи учебных ресурсов."1"Вы можете получить его бесплатно без каких-либо уловок.