1 introduction

  1. Spring is a lightweight open source framework created to address the complexities of enterprise application development. One of the main advantages of the framework is its layered architecture, which allows consumers to choose which components to use while providing an integrated framework for J2EE application development.
  2. Spring is a combination of many good design patterns (factory, singleton, proxy, adapter, wrapper, observer, template, policy).
  3. Spring’s use is not limited to server-side development. Any Java application can benefit from Spring in terms of simplicity, testability, and loose coupling.
  4. Rather than replacing existing framework products, Spring is an organic integration of many frameworks to simplify enterprise development, commonly known as “glue framework”.

2 Spring Architecture composition

The Spring architecture consists of a number of modules, which can be classified as

  • Core technologies: Dependency injection, events, resources, I18N, validation, data binding, type conversion, SpEL, AOP.
  • Testing: Mock objects, TestContext framework, Spring MVC tests, WebTestClient.
  • Data access: transaction, DAO support, JDBC, ORM, marshaling XML.
  • Spring MVC and Spring WebFlux Web Framework.
  • Integration: remote processing, JMS, JCA, JMX, email, tasks, scheduling, caching.
  • Languages: Kotlin, Groovy, dynamic languages.
  • List item

The Spring architecture consists of the following figure

3 Spring Environment Construction

3.1 Pom.xml introduces common Spring dependencies

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > The < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Qf < / groupId > < artifactId > hello - spring < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < dependencies > <! <dependency> <groupId>org.springframework</groupId> <artifactId> Spring-context </artifactId> < version > 5.1.6. RELEASE < / version > < / dependency > < / dependencies > < project >Copy the code

3.2 Creating a Spring Configuration File

XML, applicationContext. XML, beans.xml

<? The 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>Copy the code

4 Spring Factory Coding (getting started)

4.1 Defining the target Bean type

public class MyClass{ public void show(){ System.out.println("HelloWorld"); }}Copy the code

4.2 < beans > internally configured beans in spring-context.xml

After configuring MyClass’s beans in spring-context.xml, when the project starts, the Spring container automatically creates an instance of MyClass named MC

<! - configuration instance (id: "unique identifier" class = "need to be created a target object fully qualified name") - > < bean id = "MC" class = "com. Qf. Spring. Part1. Factory. MyClass" / >Copy the code

The test code

Public class TestFactory{/** * All objects in the application are created by Spring's ApplicationContext factory. */ public static void main(String[] args){ //1\. Needed to create the bean object reading configuration files, and access to a factory object ApplicationContext CTX = new ClassPathXmlApplicationContext (" spring - context. XML "); MyClass MC = (MyClass) ctx.getBean(" MC "); //2\. //3\. Use object Mc.show (); }}Copy the code

5 IoC (Inversion of Control

Inversion of control is the core of the Spring framework. The so-called inversion of control means that the application itself is not responsible for the creation and maintenance of dependent objects, and the creation and maintenance of dependent objects are taken care of by external containers. In this way, the control is transferred from the application to the external container. This changes from creating dependent objects yourself to creating them by the Spring container. (Change from active to passive, that is, reverse). Inversion of control resolves the strong coupling between components that have dependencies, making the project shape more robust.

5.1 Strong coupling in the project

public class UserDAOImpl implements UserDAO{.... }Copy the code
Public class UserServiceImpl implements UserService {// UserDAOImpl implements UserService in the traditional new way!! UserServiceImpl is not robust!! private UserDAO userDAO= new UserDAOImpl(); @Override public User queryUser() { return userDAO.queryUser(); }... }Copy the code

5.2 Solution

Public class UserServiceImpl implements UserService {//!!! No more coupling of ANY DAO implementations!! , eliminate unstable factors!! Private UserDAO UserDAO; Getters And setters@override public User queryUser() {return {Getters And setters@override public User queryUser() {return userDAO.queryUser(); }... }Copy the code

Configure the beans corresponding to the UserDAO and UserService in the Spring configuration file

<bean id="userDAO" class="com.qf.spring.part1.injection.UserDaoImpl"></bean> <! - UserServiceImpl component - > < bean id = "userService" class = "com. Qf. Spring. Part1. Injection. UserServiceImpl" > <! <property name="userDAO" ref="userDAO"/> </bean>Copy the code

6 Dependency Injection (DI) Dependency Injection

6.1 concept

When Spring creates an object, it assigns values to its properties, called dependency injection. There are two main methods of injection

  • Constructor injection
  • Setter method injection

6.2 Setter method injection

When you create an object, the Spring factory assigns values to the properties of the object through Setter methods.

6.2.1 Defining the target Bean type

public class User {
    private Integer id;
    private String password;
    private String sex;
    private Integer age;
    private Date bornDate;
    private String[] hobbys;
    private Set<String> phones;
    private List<String> names;
    private Map<String,String> countries;
    private Properties files;
    //Getters And Setters
}

Copy the code

6.2.2 Basic Type + String Type + Date Type

<bean id="u1" class="com.qf.spring.part1.injection.User"> <! --base field--> <property name="id" value="1001" /> <property name="password" value="123456" /> <property name="sex" value="male" /> <property name="age" value="20" /> <property name="bornDate" value="1990/1/1" /><! Note the format "/"--> </bean>Copy the code

6.2.3 Container Types (List, Set, Map,Properties)

<bean id="u1" class="com.qf.spring.part1.injection.User"> <! --Array--> <property name="hobbys"> <array> <value>Run</value> <value>Swim</value> <value>Climb</value> </array> </property> <! --Set--> <property name="phones"> <set> <value>13777777777</value> <value>13888888888</value> <value>13999999999</value>  </set> </property> <! --List--> <property name="names"> <list> <value>tom</value> <value>jack</value> <value>marry</value> </list> </property> <! --Map--> <property name="countries"> <map> <entry key="CN" value="China" /> <entry key="US" value="America" /> <entry key="KR" value="Korea" /> </map> </property> <! --Properties--> <property name="files"> <props> <prop key="first">One</prop> <prop key="second">Two</prop> <prop key="third">Three</prop> </props> </property> </bean>Copy the code

6.2.4 User-defined Types

<! -- Secondary bean, Be as properties - > < bean id = "addr" class = "com. Qf. Spring. Part1. Injection. Address" > < property name = "position" value = "haidian district" / > <property name="zipCode" value="100001" /> </bean> <! - main beans, the main body of operation - > < bean id = "u2" class = "com. Qf. Spring. Part1. Injection. The User" > < property name = "address" ref = "addr" / > <! -- Address property references addr object --> </bean>Copy the code

6.3 Structural injection

When an object is created, the Spring factory assigns values to its properties via constructors.

6.3.1 Defining the target Bean type

public class Student { private Integer id; private String name; private String sex; private Integer age; //Constructors public Student(Integer id , String name , String sex , Integer age){ this.id = id; this.name = name; this.sex = sex; this.age = age; }}Copy the code

6.3.2 injection

<! Injection - structure - > < bean id = "u3" class = "com. Qf. ZCG. Spring. Day1. T2. The ioc. The Student" > < constructor - arg name = "id" value = "1234" / > <! -- Except for the label name change, <constructor-arg name="name" value=" Tom "/> <constructor-arg name="age" value="20" /> <constructor-arg name="sex" value="male" /> </bean>Copy the code

7 Spring Factory features

7.1 Han-style to create advantages

After the factory is created, all objects in the Spring configuration file will be created (hungry style), improving the application efficiency, avoiding multiple I/OS, and reducing the object creation time. (The concept is similar to connection pool, created once, accessed directly when used)

7.2 Lifecycle approach

  • Custom initialization method: Add the “init-method” property and Spring will call this method after the object is created.
  • Custom destroy methods: Add the “destroy-method” property, and Spring will call this method before destroying the object.
  • Destroy: After the factory’s close() method is called, Spring destroys all created singletons.
  • Classification: Singleton objects destroyed by the Spring container, Prototype objects destroyed by the JVM.

7.3 Life cycle Notes

import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; Public void init(){system.out.println ("init method executed"); } @destroy // Destroy public void destroy(){system.out.println ("destroy method executed"); }Copy the code

7.4 Life cycle stages

Singleton bean: singleton

Create == “constructor ==” set method (injected value) == “init(initialized) ==” build completion == “destroy with factory shutdown

Multiple example beans: Prototype

When used, create == constructor == Set method (injected value) == init(initialized) == completion == JVM garbage collection destruction

8 Agent design mode

8.1 concept

Separating core functions from auxiliary functions (transaction, log, performance monitoring code) makes core business functions purer and auxiliary business functions reusable.

8.2 Static proxy design mode

Through the object of the proxy class, adding auxiliary functions for the object of the original class (object of the target class), it is easier to change the proxy implementation class and facilitate maintenance.

  • Proxy class = implements the same interface as the original class + adds accessibility + calls the business methods of the original class.
  • Static proxy problems
    • There are too many proxy classes, which is not good for project management.
    • The auxiliary function code of multiple proxy classes is redundant, and when modified, the maintainability is poor.

8.3 Dynamic Proxy Design Mode

8.3.1 JDK Dynamic Proxy Implementation (interface-based)

Final OrderService OS = new OrderServiceImpl(); Handler = new InvocationHandler(){//1. @override Public Object Invoke (Object proxy, Method Method, Object[] args) throws Throwable { System.out.println("start..." ); method.invoke(os, args); System.out.println("end..." ); return null; }}; Object proxyObj = proxy. newProxyInstance(ClassLoader, Interfaces, InvocationHandler);Copy the code

8.3.2 CGlib Dynamic Proxy Implementation (Based on Inheritance)

final OrderService os = new OrderServiceImpl(); Enhancer cnh = new Enhancer(); Enh.setsuperclass (os.getClass()); Enh. setCallback(new InvocationHandler(){//3. @override Public Object Invoke (Object proxy, Method Method, Object[] args) throws Throwable{ System.out.println("start..." ); Object ret = method.invoke(os,args); System.out.println("end..." ); return ret; }}); OrderService proxy = (OrderService)enh.create(); Create dynamic proxy class proxy,createOrder();Copy the code

Section oriented programming

9.1 concept

Aspect Oriented Programming (AOP), or section-oriented Programming, uses a technique called “crosscutting” to cut open the interior of wrapped objects and encapsulate the common behavior that affects multiple classes into a reusable module named “Aspect”, or Aspect. The so-called “facets”, simply speaking, are those unrelated to the business, but are encapsulated by the logic or responsibility of business modules, which is convenient to reduce the repetitive code of the system, reduce the degree of coupling between modules, and is conducive to the future operability and maintainability.

In popular terms, section-oriented programming is the practice of doing some extra horizontal processing of the propped object’s methods at certain execution times (before, after, or when the method throws an exception). The benefits are: 1. We can extend our content horizontally without modifying the original code; 2. Unify the common logic in some methods.

The difference between OOP(object-oriented programming) and AOP(aspect oriented programming) is that OOP extends classes vertically; Aop is a horizontal extension.

9.2 AOP development terminology

  • Join Points: Join points are methods that exist objectively in application classes and can be intercepted by Spring to cut into content.
  • Pointcut: Join points that are cut into.
  • Advice: Additional capabilities can be added to pointcuts: pre-notification, post-notification, exception notification, surround notification, and so on.
  • Target: The Target object of the agent
  • Weaving: The process of applying notifications to specific classes to create new proxy classes.
  • Proxy: The resulting class that is woven into the advice by AOP.
  • Aspect: Consists of pointcuts and notifications that weave crosscutting logic into the join points specified by the Aspect.

9.3 role

Spring’s AOP programming is all about adding helper functionality to the methods of the original class through dynamic proxy classes.

9.4 Environment Construction

Introduce AOP-related dependencies

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> < version > 5.1.6. RELEASE < / version > < / dependency >Copy the code

Spring-context.xml is introduced into the AOP namespace

<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> </beans>Copy the code

9.5 Development Process

Defining primitive classes

package com.qf.aaron.aop.basic;

public interface UserService {
    public void save();
}

Copy the code
package com.qf.aaron.aop.basic;

public class UserServiceImpl implements UserService {
    public void save() {
        System.out.println("save method executed...");
    }
}

Copy the code

Define notification classes (add additional functionality

package com.qf.aaron.aop.basic; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; Public class MyAdvice implements MethodBeforeAdvice public void before(Method Method, Object[] args, Object target) throws Throwable { System.out.println("before advice executed..." ); }}Copy the code

Defining bean labels

<! - the original object - > < bean id = "us" class = "com. Qf. Aaron. Aop. Basic. UserServiceImpl" / > <! - auxiliary object - > < bean id = "myAdvice" class = "com. Qf. Aaron. Aop. Basic. MyAdvice" / >Copy the code

Defining pointcuts

Form an Aspect

<aop:config> <! <aop:pointcut id="myPointCut" expression="execution(* save())" <aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" /> </aop:config>Copy the code

9.6 notify the class

There are six notification classes that can be defined, and you can choose the notification class as required.

Before advice Postnotification: AfterAdvice Postnotification: AfterReturningAdvice // An exception is not executed, the method ends because of an exception, no return value Exception notification: ThrowsAdvice Surround notification: MethodInterceptorCopy the code

9.7 JDK dynamic proxy and CGLIB dynamic proxy selection

  • Spring base includes JDK proxy and Cglib proxy
  • The basic rule is: the target business class uses a JDK proxy if it has an interface, and a CGLib proxy if it does not

However, JDK dynamic proxy is enabled in Spring by default. To use CGLIB dynamic proxy, you need to configure it in the Spring configuration file.

<! < AOP :aspectj-autoproxy proxy-target-class="true"/>Copy the code

AOP implementation based on aspectJ

Writing aspectJ notification code:

@ Aspect public class AspectJAdvisor {/ / notify @ Around round (" execution (* org. Example. Service. Impl. *. * (..) )") public Object timer(ProceedingJoinPoint PJP) throws Throwable{system.out.println ("前 提 "); Object o = pjp.proceed(); System.out.println(" [after notification] "); return o; } / / rear @ After notice (" execution (* org. Example. Service. Impl. *. * (..) )") public void after(JoinPoint jp) throws Throwable{ System.out.println("====After method invokded===="); } / / pre notice @ Before (" execution (* org. Example. Service. Impl. *. * (..) )") public void before(JoinPoint jp){ System.out.println("====before method invoked===="); } / / normal return to inform @ AfterReturning (" execution (* org. Example. Service. Impl. *. * (..) )") public void afterReturning(JoinPoint jp){ System.out.println("====after value return===="); } // The method exception must be the same as the exception thrown by the proxy class, Throwing the value to be consistent with the abnormal parameter name @ AfterThrowing (value = "execution (* org. Example. Service. Impl. *. * (..) )", throwing="npe") public void afterThrowException(JoinPoint jp, NullPointerException npe){ System.out.println("====after exception throwing===="); }}Copy the code

configuration

<bean id="userService" class="org.example.service.impl.UserServiceImpl"></bean> <bean id="throwsAdvisor" class="org.example.advisor.AspectJAdvisor"></bean> <! < AOP :aspectj-autoproxy proxy-target-class="true"></ AOP :aspectj-autoproxy>Copy the code

Development based on annotations

11.1 the statement bean

A <bean to replace a component of a self-built type… > tag. Beans can be declared faster

  • @Service Business class specific @Repository DAO implementation class specific @Controller Web layer specific
  • @ Component of general
  • The @scope user controls the creation mode of the bean
// @service indicates that this class is a business class. <bean class=" XXX.UserServiceImpl"> // @service default beanId == lowercase class name "UserServiceImpl" // @service ("userService") define the beanId as "userService" @service // declare the bean with id="userServiceImpl" @scope ("singleton") // declare the creation mode, The default mode is singleton. @scope ("prototype") public Class UserServiceImpl implements UserService {... }Copy the code

11.2 injection (DI)

Used to complete the injection of property values in the bean

  • @autoWired Automatic injection based on type
  • @resource is automatically injected based on the name
  • The @qualifier (” userDAO “) specifies the ID of the bean to be injected automatically, usually in conjunction with @AutoWired
  • @value Inject simple type data (jdk8 types +String)
@service public class UserServiceImpl implements UserService {@autoWired @Qualifier("userDAO2") // If there are multiple beans of type UserDAO, you can use this annotation to pick a private UserDAO UserDAO; }Copy the code
@service public class UserServiceImpl implements UserService {@resource ("userDAO3") // Add bean private = "userDAO3" UserDAO userDAO; /* @resource // Inject bean with id= "userDAO" private userDAO userDAO; * /}Copy the code
Public class XX{@value ("100") private Integer ID; @value ("shine") // Private String name; }Copy the code

11.3 Transaction Control

Used to control transaction entry

  • @Transactional
// Every method in a class cuts into a transaction (except for methods that have their own transaction control) @Transactional(isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception. class,timeout = -1) public class UserServiceImpl implements UserService { ... // The method has its own transaction control, @transactional (Propagation =Propagation.SUPPORTS) public List<User> queryAll() {return userDao.queryAll(); } public void save(User user){ userDao.save(user); }}Copy the code

11.4 Annotations Required configuration

<! Tell Spring which packages have annotated classes, methods, properties --> <! -- <context:component-scan base-package="com.qf.a,com.xx.b"></context:component-scan> --> <context:component-scan base-package="com.qf"></context:component-scan> <! Tell Spring that @Transactional customizes a transaction Based on txManager = DataSourceTransactionManager - > < tx: annotation - driven transaction - manager = "txManager" / >Copy the code

11.5 AOP development

11.5.1 Use of Annotations

import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @aspect // Declare this class to be an Aspect class: Contains pointcut and advice @component // declaration components, Enter the factory public class MyAspect {/ / define breakthrough point the @pointcut (" execution (* com in qf. Spring. Service. UserServiceImpl. * (..) )") public void PC (){} @before (" PC ()") public void myBefore (JoinPoint a) { System.out.println("target:"+a.getTarget()); System.out.println("args:"+a.getArgs()); System.out.println("method's name:"+a.getSignature().getName()); System.out.println("before~~~~"); } @afterreturning (value=" PC ()",returning="ret") public void myAfterReturning(JoinPoint A,Object RET){ System.out.println("after~~~~:"+ret); } @around (" PC ()") public Object myInterceptor(ProceedingJoinPoint P) throws Throwable { System.out.println("interceptor1~~~~"); Object ret = p.proceed(); System.out.println("interceptor2~~~~"); return ret; } @afterthrowing (value=" PC ()",throwing="ex") public void myThrows(JoinPoint JP,Exception ex){ System.out.println("throws"); System.out.println("===="+ex.getMessage()); }}Copy the code

11.5.2 configuration

<! Aop :aspectj-autoproxy </ AOP :aspectj-autoproxy>Copy the code

Spring unit testing

12.1 Importing Dependencies

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.6.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId> The < version > 4.12 < / version > < / dependency >Copy the code

12.2 Test Coding

The factory creation process can be eliminated;

You can inject the component to be tested directly into the test class.

@ RunWith (SpringJUnit4ClassRunner. Class) / / by SpringJUnit4ClassRunner start testing @ ContextConfiguration (" classpath: applicationContext. XML ") / / spring configuration file location public class SpringTest {/ / the current test class will also be included in the factory, @qualifier ("userDAO") private userDAO userDAO; @test public void Test (){// Test using userDAO userdao.queryUser (); . }}Copy the code

The last

You can leave a comment below to discuss what you don’t understand. You can also pay attention to my private letter and ask me. I will answer it after I see it. Also welcome everyone to pay attention to my official account: bright future, Golden Three silver four job-hunting interview season, sorted out more than 1000 nearly 500 pages of PDF documents of Java interview questions, articles will be updated in it, sorted out the information will be placed in it. Thank you for watching, think the article is helpful to you remember to pay attention to me a thumb-up support!