Careful thought. . No need to repeat-create the wheel.
What a day to review the direct CTRL CV
https://gitee.com/SnailClimb/JavaGuide/blob/master/docs/system-design/framework/spring/Spring-Design-Patterns.md#
Inversion of Control (IoC) and dependency injection (DI)
IoC (Inversion of Control, control flip) is Spring in a very, very important concept, it is not a technology, but a decoupled design. Its main purpose is to achieve decoupling between objects having dependency by means of "third party" (Spring container in the IOC) (the IOC easy to manage objects, you can just use), thereby reducing the coupling between the code . IOC is a principle, instead of a pattern, the following modes (but not limited to) the IoC principle achieved.
Spring IOC container are like a factory, when we need to create an object, you can just configure the configuration file / annotation can be, no need to consider how objects are created out of. IOC container is responsible for creating objects, connect objects together, configure these objects, and to process the entire lifecycle from the creation of these objects until they are completely destroyed.
In a real project a Service class if there are hundreds or even thousands of class as its bottom, we need to instantiate the Service, you may want to find out every time the constructor of this Service all the underlying class, which could put people crazy. If the use of the IOC, you only need to configure, and where necessary quoted on the line, which greatly increases the maintainability of the project and reduce the development effort. About Spring IOC understanding, it is recommended to see which look almost know one answer: https://www.zhihu.com/question/23277575/answer/169698662 , very good.
? Control Flip how to understand it give an example: "Object a dependent object b, when the object is a need to use the object b must be to create their own but when the system was introduced IOC container, before the object a and object b lost. a direct link. this time, when the object is a need to use the object b, we can specify the IOC container to create an object b injected into a subject in. " The process of obtaining a target dependent objects b by the proactive behavior becomes a passive behavior, control of the flip, the origin of which is to control the reversal of the name.
DI (Dependecy Inject, dependency injection) is controlled to achieve a design pattern is inverted, that is the instance variable dependency injection into an object to pass.
Factory design pattern
Spring can use the factory pattern BeanFactory
or ApplicationContext
create a bean object.
Comparison between the two:
BeanFactory
: Delayed implantation (when using the bean will be injected to a), compared toBeanFactory
who will take up less memory, programs start faster.ApplicationContext
: Container startup, whether you use to useless, disposable create all bean.BeanFactory
Provides only the most basic dependency injection support,ApplicationContext
expandedBeanFactory
, in addition toBeanFactory
features include additional more features, it is generally developersApplicationContext
will be more.
ApplicationContext realization of three categories:
ClassPathXmlApplication
: Document as the context classpath resources.FileSystemXmlApplication
: Loaded from the file system XML file context definition information.XmlWebApplicationContext
: Load context definition information from the Web system in XML files.
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 design pattern
In our system, there are some objects in fact, we only need one, for example: the thread pool, cache, dialog, registry, log object, the object serves as a device driver for your printer, graphics and so on. In fact, this type of object can only have one instance, if you create multiple instances of it could lead to some problems, such as: abnormal behavior of the program, and the resource overage, or inconsistency of the results.
The benefits of using Singleton pattern:
- For frequently used objects, you can create omit the time it takes an object, which for those heavyweight objects, is very respectable amount of system overhead;
- Due to the reduced number of new operations, and thus the frequency of use of system memory will be reduced, which will relieve pressure GC, GC pause times shortened.
The default scope in Spring bean is singleton (single example). In addition to the singleton scope, Spring bean in scope as well as the following categories:
- prototype: every request to create a new bean instance.
- request: Each HTTP request will generate a new bean, which is only valid in the current HTTP request.
- session: Each HTTP request will generate a new bean, which is only valid in the current HTTP session.
- global-session: the global session scope, only the portlet web-based application makes sense, Spring5 gone. Portlet is capable of generating a semantic code (eg: HTML) Small Java Web plugin fragments. They are based portlet container may be treated as HTTP servlet request like. However, the servlet different, each has a different portlet session
Example implementations of a single Spring:
- xml :
<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
- annotation:
@Scope(value = "singleton")
Spring by ConcurrentHashMap
single-mode specific embodiments manner singleton registry. Spring core code implemented as a single embodiment of
// 通过 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));
}
}
}
Proxy design pattern
Application proxy mode in the AOP
AOP (Aspect-Oriented Programming: Oriented Programming) can be those regardless of the service, but a logical or liabilities (such as transaction processing, log management, access control, etc.) service module jointly called encapsulated , to facilitate code duplication reduction system , to reduce the coupling between modules , and is conducive to the future scalability and maintainability .
Spring AOP is the dynamic agent-based , if you want to proxy object implements an interface, then Spring AOP will use JDK Proxy , to create a proxy object, but the object does not implement an interface, you can not use the JDK Proxy to proxy the this time Spring AOP uses Cglib , this time Spring AOP uses Cglib generating a subclass of the object as a proxy agent, as shown below:
Of course, you can also use AspectJ, Spring AOP has been integrated with AspectJ, AspectJ should be counted on the Java ecosystem is the most complete of the AOP framework.
After using AOP we can put some common functions abstracted, use can be used directly where it is needed, which greatly simplifies the code amount. It is also convenient when we need to add new features, which would also increase the scalability of the system. Logging, transaction management, and so on scene have used the AOP.
Spring AOP and AspectJ AOP What is the difference?
Enhanced belonging run Spring AOP, and AspectJ is an enhanced compilation. Spring AOP based agent (Proxying), based on the AspectJ bytecode manipulation (Bytecode Manipulation).
Spring AOP has been integrated with AspectJ, AspectJ should be counted on the Java ecosystem is the most complete of the AOP framework. Spring AOP AspectJ compared to the more powerful, but Spring AOP relatively more simple,
If we cut surface is relatively small, so little performance difference between the two. However, when cut too much, the best choice for AspectJ, it is much faster than Spring AOP.
Template Method
Template Method design pattern is a behavioral pattern that defines a skeleton of the algorithm operation, some steps to subclasses delay. Template Method lets subclasses may not change the structure of an algorithm to redefine certain steps of the implementation of the algorithm.
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() {
//当前类实现
}
}
In Spring jdbcTemplate
, hibernateTemplate
or the like to the end of the class Template database operations, they are used to model the template. Under normal circumstances, we are achieved using template inheritance pattern of the way, but Spring does not use this method, but using Callback Mode and Template Method pattern fit only achieve the effect of code reuse, as well as increased flexibility .
Observer Pattern
The observer pattern is an object behavioral patterns. It indicates the kind of object having a dependency between the object and, when an object is changed, the object of the dependent object will respond. Spring event-driven model is the Observer pattern of a classic application. Spring event-driven model is very useful in many scenarios can decouple our code. For example, every time we add commodities when they are required to re-update commodity index, this time we can use the observer pattern to solve this problem.
Spring event-driven model of the three roles
Events role
ApplicationEvent
( org.springframework.context
Role under the package) to act as an event, this is an abstract class that inherits java.util.EventObject
and implements java.io.Serializable
the interface.
Spring in the presence of the following events by default, they are to ApplicationContextEvent
achieve (inherited from ApplicationContextEvent
):
ContextStartedEvent
:ApplicationContext
Event-triggered after the start;ContextStoppedEvent
:ApplicationContext
Event after triggering stop;ContextRefreshedEvent
:ApplicationContext
Initialization or refresh event after the completion of the trigger;ContextClosedEvent
:ApplicationContext
Event-triggered after closing.
Event listener role
ApplicationListener
Act as an event listener role, it is an interface, which defines a single onApplicationEvent()
method to deal with ApplicationEvent
. ApplicationListener
Source interface class as can be seen in the interface definition of the event as long as the interface seen achieve ApplicationEvent
it. So, as long as we achieve in Spring ApplicationListener
interface onApplicationEvent()
method to complete the listening event
package org.springframework.context;
import java.util.EventListener;
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}
Event Publisher role
ApplicationEventPublisher
Served as publisher of events, it is also an interface.
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
ApplicationEventPublisher
Interface of publishEvent()
this method AbstractApplicationContext
is implemented in a class, read implement this method, you'll find that it really is an event by ApplicationEventMulticaster
coming out of the broadcast. Specific content too much, not analyzed here, behind might write a separate article mentioned.
Spring flow of events summary
- Define an event: a realization inherits from
ApplicationEvent
, and write the corresponding constructor; - Define an event listener: Implement
ApplicationListener
Interface, rewritingonApplicationEvent()
method; - Use the event publisher announced: by
ApplicationEventPublisher
thepublishEvent()
way to publish news.
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));
}
}
When you call DemoPublisher
the publish()
method when, for example demoPublisher.publish("你好")
, the console will print out: 接收到的信息是:你好
.
Adapter mode
Adapter mode (Adapter Pattern) to a desired conversion interface into another interface to the client, so that the class interface adapter mode may be incompatible with the work, which alias wrapper (Wrapper).
The adapter mode spring AOP
We know that to achieve Spring AOP is based on proxy mode, but Spring AOP enhancements or notification (Advice) to use the adapter mode, the associated interface is AdvisorAdapter
. Advice common types are: BeforeAdvice
(before the target method call, pre-notification), AfterAdvice
(after the target method invocation, after advice), AfterReturningAdvice
(after the execution of the target method, before the return) and so on. Each type of the Advice (notification) has a corresponding blockers: MethodBeforeAdviceInterceptor
, AfterReturningAdviceAdapter
, AfterReturningAdviceInterceptor
. Spring predefined notification through the corresponding adapter, adapted to MethodInterceptor
the type of object interface (Method interceptor) (eg: MethodBeforeAdviceInterceptor
in charge of adapting MethodBeforeAdvice
).
spring MVC in adapter mode
In the Spring MVC, DispatcherServlet
according to call request information HandlerMapping
, corresponding to the resolution request Handler
. Resolved to the corresponding Handler
(that is, we usually say Controller
after the controller), starting from the HandlerAdapter
process adapter. HandlerAdapter
As a desired interface implementation class specific adapter for adapting the target class, Controller
a class adapter required.
Why use Spring MVC in adapter mode? Spring MVC are Controller
many kinds and types of Controller
different methods for processing by the request. If not, then the use of the adapter mode, DispatcherServlet
direct access to a corresponding type Controller
, it is necessary to self-determination, the same code as follows:
if(mappedHandler.getHandler() instanceof MultiActionController){
((MultiActionController)mappedHandler.getHandler()).xxx
}else if(mappedHandler.getHandler() instanceof XXX){
...
}else if(...){
...
}
If we add one more Controller
type of statement would then add a line judge in the above code, this form would make the program difficult to maintain, but also violated the principle of opening and closing the design mode - open to extension but closed for modification.
Decorator Pattern
The decorator pattern to an object can dynamically add some additional attributes or behavior. Compared to the use of inheritance, the decorator pattern is more flexible. Simple little say is that when we need to modify the original function, but we do not want to go directly to modify the original code, the original design of the code outside a Decorator sets in. In fact, there are many places in the JDK uses the decorator pattern, such as InputStream
family, InputStream
have lower class FileInputStream
(read document), BufferedInputStream
(increase the cache, greatly enhance the speed of reading the file) and other sub-classes without modifying InputStream
the extended code case its functionality.
Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。我们能否根据客户的需求在少修改原有类的代码下动态切换不同的数据源?这个时候就要用到装饰者模式(这一点我自己还没太理解具体原理)。Spring 中用到的包装器模式在类名上含有 Wrapper
或者 Decorator
。这些类基本上都是动态地给一个对象添加一些额外的职责
总结
Spring 框架中用到了哪些设计模式?
- 工厂设计模式 : Spring使用工厂模式通过
BeanFactory
、ApplicationContext
创建 bean 对象。 - 代理设计模式 : Spring AOP 功能的实现。
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板方法模式 : Spring 中
jdbcTemplate
、hibernateTemplate
等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。 - 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配
Controller
。 - ......
参考
- 《Spring技术内幕》
- https://blog.eduonix.com/java-programming-2/learn-design-patterns-used-spring-framework/
- http://blog.yeamin.top/2018/03/27/ singleton -Spring single embodiment implementation principle Analysis /
- https://www.tutorialsteacher.com/ioc/inversion-of-control
- https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html
- https://juejin.im/post/5a8eb261f265da4e9e307230
- https://juejin.im/post/5ba28986f265da0abc2b6084