1. Spring overview
1.1 INTRODUCTION
- Spring: spring -- > brings spring to the software industry
- In 2002, Rod Jahnson first launched the Spring framework prototype interface21 framework.
- On March 24, 2004, the Spring framework was redesigned based on the interface 21 framework and released the official version of 1.0.
- It's hard to imagine Rod Johnson's degree. He is a doctor at the University of Sydney. However, his major is not computer, but musicology.
- Spring concept: make the existing technology more practical. Itself is a hodgepodge, integrating existing framework technologies
Official website: spring.io/
Official download address: repo.spring.io/libs-releas...
GitHub : github.com/spring-proj...
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.0.RELEASE</version> </dependency> Copy code
1.2 advantages
- Spring is an open source free framework (container)!
- Spring is a lightweight, non intrusive framework!
- Inversion of control (IOC), aspect oriented programming (AOP)!
- Support transaction processing and framework integration!
To sum up: Spring is a lightweight inversion of control (IOC) and aspect oriented programming (AOP) framework!
1.3 composition
The spring framework is a layered architecture consisting of seven well-defined modules. Spring module is built on the core container, which defines the way to create, configure and manage bean s
Each module (or component) that makes up the Spring framework can exist alone or be implemented jointly with one or more other modules. The functions of each module are as follows:
-
Spring Core: the core container provides the basic functions of the spring framework. The main component of the core container is BeanFactory, which is the implementation of the factory pattern. BeanFactory uses the (IOC) pattern to separate the configuration and dependency specifications of the application from the actual application code.
-
Spring Context: Spring context is a configuration file that provides context information to the spring framework. The spring context includes enterprise services such as JNDI, EJB, e-mail, internationalization, checksum and scheduling capabilities.
-
Spring AOP: through the configuration management feature, the spring AOP module directly integrates aspect oriented programming functions into the spring framework. Therefore, you can easily make the spring framework manage any object that supports AOP. The spring AOP module provides transaction management services for objects in spring based applications. By using spring AOP, declarative transaction management can be integrated into applications without relying on components.
-
Spring DAO: the JDBC DAO abstraction layer provides a meaningful exception hierarchy that can be used to manage exception handling and error messages thrown by different database vendors. The exception hierarchy simplifies error handling and greatly reduces the amount of exception code that needs to be written (such as opening and closing connections). Spring DAO's JDBC oriented exceptions follow a common DAO exception hierarchy.
-
Spring ORM: the spring framework inserts several ORM frameworks to provide ORM object relationship tools, including JDO, Hibernate and iBatis SQL Map. All of this follows spring's common transaction and DAO exception hierarchy.
-
Spring Web: the spring web module is built on the application context module and provides context for web-based applications. Therefore, the spring framework supports integration with Jakarta Struts. The web module also simplifies processing multipart requests and binding request parameters to domain objects.
-
Spring MVC framework: the MVC framework is a fully functional MVC implementation for building Web applications. Through the policy interface, the MVC framework becomes highly configurable. MVC accommodates a large number of view technologies, including JSP, Velocity, Tiles, iText and POI.
1.4 expansion
Spring Boot and Spring Cloud
- Spring Boot is a set of rapid configuration scaffolds of spring, which can quickly develop a single microservice based on Spring Boot;
- Spring Cloud is implemented based on Spring Boot;
- Spring Boot focuses on a single micro service individual that is fast and easy to integrate. Spring Cloud focuses on the overall service governance framework;
- Spring Boot uses the concept of constraint over configuration. Many integration schemes have been selected for you. You can't configure without configuration,
- A large part of Spring Cloud is implemented based on Spring Boot. Spring Boot can be used independently of Spring Cloud for development projects, but Spring Cloud cannot be separated from Spring Boot and belongs to dependency.
- SpringBoot plays a connecting role in SpringClound. If you want to learn spring cloud, you must learn SpringBoot.
2. IOC essence
Inversion of control (IoC) is a design idea. DI (dependency injection) is a method to realize IoC. Some people think that DI is just another way of saying IoC. In programs without IoC, we use object-oriented programming. The creation of objects and the dependencies between objects are completely hard coded. In programs, the creation of objects is controlled by the program itself. After the control is reversed, the creation of objects is transferred to a third party. Personally, I think the so-called control reversal is the reversal of the way to obtain dependent objects.
IOC is the core content of the Spring framework. IOC is perfectly implemented in a variety of ways. You can use XML configuration or annotations. The new version of Spring can also implement IOC with zero configuration. During initialization, the Spring container reads the configuration file first, creates and organizes objects according to the configuration file or metadata, and stores them in the container. When the program is used, it takes out the required objects from the IOC container.
3,HelloSpring
3.1. Import Jar package
Note: spring needs to import commons logging for logging We use maven, which will automatically download the corresponding dependencies
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.10.RELEASE</version> </dependency> Copy code
3.2. Code writing
- Write an entity class
package com.angus.pojo; /** * @description: * @author: angus * @date: 2021/12/13 10:14 */ public class Hello { private String name; public String getName() { return name; } public void setName(String str) { this.name = str; } public void show(){ System.out.println("Hello," + name ); } } Copy code
- Write our spring file, here we name it beans 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"> <!--use Spring To create an object, in Spring These are called Bean Type variable name = new type(); Hello hello = new Hello(); id = Variable name class = new Object of property It is equivalent to setting a value for the attribute in the object! --> <bean id="hello" class="com.angus.pojo.Hello"> <property name="name" value="NameOfSpring"/> </bean> </beans> Copy code
- test
@Test public void test(){ //Parse beans XML file to generate and manage the corresponding Bean objects ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //getBean: the parameter is the id of the bean in the spring configuration file Hello hello = (Hello) context.getBean("hello"); hello.show(); } Copy code
3.3 thinking
- Who created the hello object? [the hello object is created by Spring]
- How are the properties of the Hello object set? [the properties of the Hello object are set by the Spring container]
This process is called control reversal:
- Control: who controls the creation of objects? Traditional application objects are created by the program itself. After using Spring, objects are created by Spring
- Inversion: the program itself does not create an object, but becomes a passive receiving object
Dependency injection: it uses the set method to inject
IOC is a programming idea, from active programming to passive reception
You can browse the underlying source code through the new ClassPathXmlApplicationContext
3.4. Case modification
<?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"> <bean id="MysqlImpl" class="com.kuang.dao.impl.UserDaoMySqlImpl"/> <bean id="OracleImpl" class="com.kuang.dao.impl.UserDaoOracleImpl"/> <bean id="ServiceImpl" class="com.kuang.service.impl.UserServiceImpl"> <!--be careful: there name Is not an attribute , But set The part behind the method , Initial lowercase--> <!--Reference another bean , Not with value But with ref--> <property name="userDao" ref="OracleImpl"/> </bean> </beans> Copy code
We don't need to change it in the program at all. To realize different operations, we only need to modify it in the xml configuration file. The so-called IoC is done in one sentence: the objects are created, managed and assembled by Spring!
4. IOC object creation method
4.1. Create by parameterless construction method
- User.java
public class User { private String name; public User() { System.out.println("user Nonparametric construction method"); } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+ name ); } } Copy code
- beans.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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.kuang.pojo.User"> <property name="name" value="kuangshen"/> </bean> </beans> Copy code
- Test class
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //When the getBean is executed, the user has been created and constructed without parameters User user = (User) context.getBean("user"); //Call the method of the object user.show(); } Copy code
4.2. Create by parametric construction method
- UserT.java
public class UserT { private String name; public UserT(String name) { this.name = name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+ name ); } } Copy code
- beans.xml can be written in three ways
<!-- First basis index Parameter subscript setting --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- index Refers to the construction method , Subscript starts at 0 --> <constructor-arg index="0" value="kuangshen2"/> </bean> Copy code
<!-- The second is set according to the parameter name --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- name Refers to the parameter name --> <constructor-arg name="name" value="kuangshen2"/> </bean> Copy code
<!-- The third is set according to the parameter type --> <bean id="userT" class="com.kuang.pojo.UserT"> <constructor-arg type="java.lang.String" value="kuangshen2"/> </bean> Copy code
- test
@Test public void testT(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserT user = (UserT) context.getBean("userT"); user.show(); } Copy code
Conclusion: when the configuration file is loaded. The managed objects have been initialized!
5. Spring configuration
5.1. alias
Alias sets an alias for a bean. You can set multiple aliases
<!--Setting alias: getting Bean You can use alias to get--> <alias name="userT" alias="userNew"/> Copy code
5.2. Bean configuration
<!--bean namely java object,from Spring Create and manage--> <!-- id yes bean Identifier of,To be unique,If not configured id,name Is the default identifier If configured id,Configured again name,that name It's an alias name You can set multiple aliases,You can use commas,semicolon,Space separated If not configured id and name,Can be based on applicationContext.getBean(.class)Get object; class yes bean Fully qualified name of=Package name+Class name --> <bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello"> <property name="name" value="Spring"/> </bean> Copy code
5.3. import
Team cooperation is achieved through import
<import resource="{path}/beans.xml"/> Copy code
6. Dependency injection (DI)
- Dependency injection (DI).
- Dependency: the creation of Bean objects depends on the container The dependent resources of the Bean object
- Injection: refers to the resources that the Bean object depends on, which are set and assembled by the container
6.1 constructor injection
Refer to 4. How IOC creates objects
6.2 set injection (key)
The injected attribute must have a set method. The method name of the set method is capitalized by the initial letter of set + attribute. If the attribute is of boolean type and there is no set method, it is
Test pojo class: address java
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } Copy code
Student.java
package com.angus.pojo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; public void setName(String name) { this.name = name; } public void setAddress(Address address) { this.address = address; } public void setBooks(String[] books) { this.books = books; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public void setCard(Map<String, String> card) { this.card = card; } public void setGames(Set<String> games) { this.games = games; } public void setWife(String wife) { this.wife = wife; } public void setInfo(Properties info) { this.info = info; } public void show(){ System.out.println("name="+ name + ",address="+ address.getAddress() + ",books=" ); for (String book:books){ System.out.print("<<"+book+">>\t"); } System.out.println("\n hobby:"+hobbys); System.out.println("card:"+card); System.out.println("games:"+games); System.out.println("wife:"+wife); System.out.println("info:"+info); } } Copy code
1. Constant injection
<bean id="student" class="com.angus.pojo.Student"> <property name="name" value="Xiao Ming"/> </bean> Copy code
Test:
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } } Copy code
2. Bean injection
Note: the value here is a reference, ref
<bean id="addr" class="com.angus.pojo.Address"> <property name="address" value="Chongqing"/> </bean> <bean id="student" class="com.angus.pojo.Student"> <property name="name" value="angus"/> <property name="address" ref="addr"/> </bean> Copy code
3. Array injection
<bean id="student" class="com.angus.pojo.Student"> <property name="name" value="angus"/> <property name="address" ref="addr"/> <property name="books"> <array> <value>Journey to the West</value> <value>The Dream of Red Mansion</value> <value>Water Margin</value> </array> </property> </bean> Copy code
4. List injection
<property name="hobbys"> <list> <value>listen to the music</value> <value>watch movie</value> <value>Mountain climbing</value> </list> </property> Copy code
5. Map injection
<property name="card"> <map> <entry key="China Post" value="456456456465456"/> <entry key="build" value="1456682255511"/> </map> </property> Copy code
6. set injection
<property name="games"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property> Copy code
7. Null injection
<property name="wife"><null/></property> Copy code
8. Properties injection
<property name="info"> <props> <prop key="Student number">20190604</prop> <prop key="Gender">male</prop> <prop key="full name">angus</prop> </props> </property> Copy code
test result
6.3 realization of expansion injection
User.java: [Note: there is no parameter constructor here!]
public class User { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } } Copy code
1. P namespace injection: you need to create a constraint file in the header file
Import constraints : xmlns:p="http://www.springframework.org/schema/p" <!--P(attribute: properties)Namespace , Property should still be set set method--> <bean id="user" class="com.angus.pojo.User" p:name="Mad God" p:age="18"/> Copy code
2. c namespace injection: constraint files need to be added to the header file
Import constraints : xmlns:c="http://www.springframework.org/schema/c" <!--C(structure: Constructor)Namespace , Property should still be set set method--> <bean id="user" class="com.kuang.pojo.User" c:name="Mad God" c:age="18"/> Copy code
Problem found: it's red. We didn't write a reference structure just now! Solution: add the parameter constructor, and you can know here that c is the so-called constructor injection!
Test code:
@Test public void test02(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); System.out.println(user); } Copy code
6.4 scope of bean
In Spring, the main bodies that make up the application and the objects managed by the Spring IoC container are called beans. Simply put, a bean is an object initialized, assembled and managed by the IoC container
Among the several scopes, the request and session scopes are only used in web-based applications (don't care what web application framework you use), and can only be used in Web-based Spring ApplicationContext environment.
6.4.1 Singleton
When the scope of a bean is singleton, there will only be one shared bean instance in the Spring IoC container, and all requests for a bean will only return the same instance of the bean as long as the id matches the bean definition. Singleton is a singleton type, which automatically creates a bean object when creating a container. It exists whether you use it or not, and the object obtained each time is the same object. Note that the singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you can configure it as follows:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"> Copy code
Test:
@Test public void test03(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); User user2 = (User) context.getBean("user"); System.out.println(user==user2); } Copy code
6.4.2 Prototype
When the scope of a bean is prototype, it means that a bean definition corresponds to multiple object instances. A prototype scoped bean will cause a new bean instance to be created each time a request is made to the bean (inject it into another bean, or call the container's getBean() method programmatically). Prototype is a prototype type. It is not instantiated when we create a container. Instead, we create an object when we obtain a bean, and the object we obtain each time is not the same object. As a rule of thumb, you should use the prototype scope for stateful beans and the singleton scope for stateless beans. Define a bean as a prototype in XML, which can be configured as follows:
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> perhaps <bean id="account" class="com.foo.DefaultAccount" singleton="false"/> Copy code
6.4.3 Request
When the scope of a bean is Request, it means that in an HTTP Request, a bean definition corresponds to an instance; That is, each HTTP Request will have its own bean instance, which is created according to a bean definition. This scope is only valid in the case of web-based Spring ApplicationContext. Consider the following bean definitions:
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/> Copy code
For each HTTP request, the Spring container will create a new loginaction bean instance according to the loginaction bean definition, and the loginaction bean instance is only valid in the current HTTP request. Therefore, you can safely change the internal state of the created instance according to the needs, while the instances created according to the loginaction bean definition in other requests, You will not see these state changes specific to a request. When the processing of the request ends, the bean instance of the request scope will be destroyed.
6.4.4 Session
When the scope of a bean is Session, it means that in an HTTP Session, a bean definition corresponds to an instance. This scope is only valid in the case of web-based Spring ApplicationContext. Consider the following bean definitions:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> Copy code
For an HTTP Session, the Spring container will create a new userPreferences bean instance according to the userPreferences bean definition, and the userPreferences bean is only valid in the current HTTP Session. Like the request scope, you can safely change the internal state of the created instance as needed. For instances created according to userPreferences in other HTTP sessions, you will not see these state changes specific to an HTTP Session. When the HTTP Session is finally discarded, the beans within the scope of the HTTP Session will also be discarded.
7. Automatic assembly of Bean
- Automatic assembly is a way to use spring to meet bean dependencies
- spring will find the bean that a bean depends on in the application context.
There are three assembly mechanisms for bean s in Spring:
- Explicit configuration in xml;
- Explicit configuration in java;
- Implicit bean discovery mechanism and automatic assembly.
Here we mainly talk about the third kind: automated assembly bean.
Spring's automatic assembly needs to be implemented from two perspectives, or two operations:
- Component scanning: spring will automatically discover the bean s created in the application context;
- Autowiring: spring automatically satisfies the dependencies between bean s, which is what we call IoC/DI;
The combination of component scanning and automatic assembly exerts great power to minimize the configuration of display.
It is recommended to use annotations instead of automatic assembly xml configuration
7.1 construction of test environment
- Create a new project
- Create two new entity classes. Cat Dog has a method called
public class Cat { public void shout() { System.out.println("miao~"); } } Copy code
public class Dog { public void shout() { System.out.println("wang~"); } } Copy code
- Create a new User class User
public class User { private Cat cat; private Dog dog; private String str; } Copy code
- Writing Spring configuration files
<?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"> <bean id="dog" class="com.angus.pojo.Dog"/> <bean id="cat" class="com.angus.pojo.Cat"/> <bean id="user" class="com.angus.pojo.User"> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> <property name="str" value="qinjiang"/> </bean> </beans> Copy code
- test
public class MyTest { @Test public void testMethodAutowire() { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); user.getCat().shout(); user.getDog().shout(); } } Copy code
7.2,byName
autowire byName (automatic assembly by name) can not be checked due to the frequent errors such as missing letters and case in the process of manually configuring xml, which reduces the development efficiency. Using automatic assembly will avoid these errors and simplify the configuration.
Test:
- Modify the bean configuration and add an attribute autowire="byName"
<bean id="user" class="com.angus.pojo.User" autowire="byName"> <property name="str" value="qinjiang"/> </bean> Copy code
- Test again and the result is still output successfully!
- We modify the bean id of cat to catXXX
- Test again and execute the null pointer Java lang.NullPointerException. Because the wrong set method is found according to the byName rule, the real setCat is not executed and the object is not initialized, so a null pointer error will be reported when calling.
Summary: when a bean node has the attribute autowire byName.
- All set method names in its class, such as setCat, will be searched to obtain a string with set removed and lowercase, that is, cat.
- Go to the spring container to find whether there is an object with this string name id.
- If any, take out the injection; If not, a null pointer exception is reported.
7.3,byType
autowire byType (auto assemble by type) using autowire byType first needs to ensure that objects of the same type are unique in the spring container. If it is not unique, a non unique exception will be reported.
NoUniqueBeanDefinitionException Copy code
Test:
- Modify the bean configuration of user: autowire="byType"
- Test, normal output
- Register a cat bean object!
<bean id="dog" class="com.angus.pojo.Dog"/> <bean id="cat" class="com.angus.pojo.Cat"/> <bean id="cat2" class="com.angus.pojo.Cat"/> <bean id="user" class="com.angus.pojo.User" autowire="byType"> <property name="name" value="angus"/> </bean> Copy code
- Test, error: NoUniqueBeanDefinitionException
- Delete cat2 and change the bean name of cat! Test! Because it is assembled by type, it will not report exceptions and will not affect the final assembly
Results. Even removing the id attribute does not affect the result.
This is automatic assembly by type!
7.4 use notes
jdk1.5 start supporting annotations, spring 2 5 begin to fully support annotations.
Preparation: inject attributes by annotation.
- Introduce the context file header into the spring configuration file
xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd Copy code
Results after adding
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:annotation-config/> <bean id="dog" class="com.angus.pojo.Dog"/> <bean id="cat" class="com.angus.pojo.Cat"/> <bean id="user" class="com.angus.pojo.User"/> </beans> Copy code
- Enable attribute annotation support!
<context:annotation-config/> Copy code
7.4.1,@Autowired
- @Autowired is automatically transferred by type and does not support id matching.
- You need to import the package of spring AOP!
Test:
- Remove the set method from the User class and use the @ Autowired annotation
public class User { @Autowired private Cat cat; @Autowired private Dog dog; private String str; public Cat getCat() { return cat; } public Dog getDog() { return dog; } public String getStr() { return str; } } Copy code
- The contents of the configuration file are displayed
<context:annotation-config/> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/> Copy code
- Test, output results successfully!
@Autowired(required=false) Description: false, the object can be null; true, the object must be saved and cannot be null.
//If the allowed object is null, set required = false, and the default is true @Autowired(required = false) private Cat cat; Copy code
7.4.2,@Qualifier
- @Autowired is automatically assembled according to the type. With @ Qualifier, it can be automatically assembled according to byName
- @Qualifier cannot be used alone.
Test steps:
- Modify the content of the configuration file to ensure that there are objects of type. And the name is not the default name of the class!
<bean id="dog1" class="com.kuang.pojo.Dog"/> <bean id="dog2" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/> Copy code
- No Qualifier test was added and an error was reported directly
- Add a Qualifier annotation to the attribute
@Autowired @Qualifier(value = "cat2") private Cat cat; @Autowired @Qualifier(value = "dog2") private Dog dog; Copy code
- Test, successful output!
7.4.3,@Resource
- @If the Resource has a specified name attribute, first search the assembly by name according to the attribute;
- Secondly, assemble in the default byName mode;
- If none of the above is successful, it will be assembled automatically by byType.
- If they are not successful, an exception is reported.
Entity class:
public class User { //If the allowed object is null, set required = false, and the default is true @Resource(name = "cat2") private Cat cat; @Resource private Dog dog; private String str; } Copy code
beans.xml
<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/> Copy code
Test result: OK configuration file 2: beans XML, delete cat2
<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> Copy code
Only annotations are retained on entity classes
@Resource private Cat cat; @Resource private Dog dog; Copy code
Result: OK
Conclusion: byName search failed first; The byType search is successful.
7.5 summary
@Similarities and differences between Autowired and @ Resource:
- @Both Autowired and @ Resource can be used to assemble bean s. Can be written on a field or on a setter method.
- @Autowired is assembled by type by default (belonging to the spring specification). By default, dependent objects must exist. If null value is allowed, its required property can be set to false, such as @ Autowired(required=false). If we want to use name assembly, it can be used in combination with @ Qualifier annotation
- @Resource (belonging to J2EE complex), the assembly is performed by name by default, and the name can be specified through the name attribute. If the name attribute is not specified, when the annotation is written on the field, the default is to find the field name by name. If the annotation is written on the setter method, the default is to find the property name for assembly. When the bean matching the name cannot be found, the assembly is performed by type. However It should be noted that once the name attribute is specified, it will only be assembled by name. They have the same function. They inject objects by annotation, but the execution order is different@ Autowired byType first, @ resource byName first.
8. Using annotation development
8.1 description
After spring 4, if you want to use annotation form, you must introduce aop package
In the configuration file, a context constraint must also be introduced
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> </beans> Copy code
8.2 implementation of Bean
We used to use bean tags for bean injection, but in actual development, we usually use annotations!
- Configure which packages to scan for annotations
<!--Specify annotation scan package--> <context:component-scan base-package="com.angus.pojo"/> Copy code
- Write classes under the specified package and add annotations
@Component("user") // Equivalent to < bean id = "user" class = "currently annotated class" / > in the configuration file public class User { public String name = "angus"; } Copy code
- test
@Test public void test(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) applicationContext.getBean("user"); System.out.println(user.name); } Copy code
8.3 attribute injection
Using annotation injection properties
- You can directly add @ value("value") to the direct name without providing a set method
@Component("user") // Equivalent to < bean id = "user" class = "currently annotated class" / > in the configuration file public class User { @Value("angus") // Equivalent to < property name = "name" value = "Angus" / > in the configuration file public String name; } Copy code
- If a set method is provided, @ value("value") is added to the set method;
@Component("user") public class User { public String name; @Value("angus") public void setName(String name) { this.name = name; } } Copy code
8.4 derived notes
These annotations replace the configuration steps in the configuration file! More convenient and fast!
@Component three derived annotations
For better layering, Spring can use the other three annotations with the same functions. At present, which function is used is the same.
- @Controller: web layer
- @Service: service layer
- @Repository: dao layer
Writing these annotations is equivalent to giving this class to the Spring management assembly!
8.5 automatic assembly notes
The automatic assembly of Bean has been talked about, which can be reviewed!
8.6 scope
@scope
- Singleton: by default, Spring creates this object in singleton mode. Close the factory and all objects will be destroyed.
- prototype: multi instance mode. Close the factory and all objects will not be destroyed. The internal garbage collection mechanism will recycle
@Controller("user") @Scope("prototype") public class User { @Value("angus") public String name; } Copy code
8.7 summary
XML and annotation comparison
- XML can be applied to any scenario, with clear structure and convenient maintenance
- Annotations are not self provided classes and cannot be used. Development is simple and convenient
xml and annotation integrated development: Recommended Best Practices
- xml management Bean
- Annotation complete attribute injection
- In the process of use, there is no need to scan. The scanning is for the annotation on the class
effect:
- Make annotation driven registration to make annotations effective
- It is used to activate the annotations on the bean s that have been registered in the spring container, that is, to register with spring
- If you do not scan the package, you need to manually configure the bean
- If it is driven without annotation, the injected value is null!
8.8. Configuration based on Java classes
JavaConfig was originally a sub project of Spring. It provides Bean definition information through Java classes. In the version of Spring 4, JavaConfig has officially become the core function of Spring 4.
Test:
- Write an entity class, Dog
@Component //Mark this class as a component of Spring and put it in the container! public class Dog { public String name = "dog"; } Copy code
- Create a new config configuration package and write a MyConfig configuration class
@Configuration //Represents that this is a configuration class public class MyConfig { @Bean //Register a bean through the method. The return value here is the bean type, and the method name is the bean id! public Dog dog(){ return new Dog(); } } Copy code
- test
@Test public void test2(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); Dog dog = (Dog) applicationContext.getBean("dog"); System.out.println(dog.name); } Copy code
- Output results successfully!
How do I import other configurations?
- Let's write another configuration class!
@Configuration //Represents that this is a configuration class public class MyConfig2 { } Copy code
- In the previous configuration class, we choose to import this configuration class
@Configuration @Import(MyConfig2.class) //Import and merge other configuration classes, similar to the inculde label in the configuration file public class MyConfig { @Bean public Dog dog(){ return new Dog(); } } Copy code
We will see a lot about the configuration of this Java class in SpringBoot and SpringCloud later. We need to know the role of these annotations!
9. Agent mode
Why learn the agent mode? Because the underlying mechanism of AOP is dynamic agent!
9.1 static agent
Static agent role analysis
- Abstract role: generally implemented using interfaces or abstract classes
- Real role: the role represented
- Agent role: agent real role; After representing a real role, you usually do some ancillary operations
- Customer: use the agent role to perform some operations
The code implements rent Java is an abstract role
//Abstract role: rent a house public interface Rent { public void rent(); } Copy code
Host.java is the real role
//Real role: landlord, the landlord wants to rent the house public class Host implements Rent{ public void rent() { System.out.println("House rental"); } } Copy code
Proxy.java is the proxy role
//Agent role: Intermediary public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } //Rent a house public void rent(){ seeHouse(); host.rent(); fare(); } //House viewing public void seeHouse(){ System.out.println("Show the tenant"); } //Intermediary fee public void fare(){ System.out.println("Intermediary fee"); } } Copy code
Client . java is the customer
//Customers, general customers will find agents! public class Client { public static void main(String[] args) { //The landlord wants to rent a house Host host = new Host(); //The intermediary helps the landlord Proxy proxy = new Proxy(host); //You go to the agency! proxy.rent(); } } Copy code
Analysis: in this process, you are in direct contact with an intermediary, just like in real life. You can't see the landlord, but you still rent the landlord's house through an agent. This is the so-called agent model. The program comes from life, so people who learn programming can generally look at what happens in life more abstractly.
9.2 benefits of static agent
- It can make our real role more pure Stop paying attention to some public things
- The public business is completed by the agent, which realizes the division of business
- When the public business expands, it becomes more centralized and convenient
Disadvantages:
- With more classes and more proxy classes, the workload becomes larger Reduced development efficiency
We want the benefits of static agent, but we don't want the disadvantages of static agent, so we have dynamic agent!
9.3 re understanding of static agent
After the students' practice, let's give another example to consolidate everyone's learning! Exercise steps:
- Create an abstract role, such as the user business we usually do, which is abstracted to add, delete, modify and check!
//Abstract role: add, delete, modify and query business public interface UserService { void add(); void delete(); void update(); void query(); } Copy code
- We need a real object to complete these operations
//Real object, the person who completes the operation of addition, deletion, modification and query public class UserServiceImpl implements UserService { public void add() { System.out.println("Added a user"); } public void delete() { System.out.println("A user was deleted"); } public void update() { System.out.println("A user has been updated"); } public void query() { System.out.println("A user was queried"); } } Copy code
- The demand is coming. Now we need to add a log function. How to implement it!
- Idea 1: add code on the implementation class [trouble!]
- Idea 2: using an agent to do this, you can realize this function without changing the original business!
- Set up a proxy class to handle logs! delegable role
//Agent role, in which the implementation of log is added public class UserServiceProxy implements UserService { private UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } public void add() { log("add"); userService.add(); } public void delete() { log("delete"); userService.delete(); } public void update() { log("update"); userService.update(); } public void query() { log("query"); userService.query(); } public void log(String msg){ System.out.println("Yes"+msg+"method"); } } Copy code
- Test access class:
public class Client { public static void main(String[] args) { //Real business UserServiceImpl userService = new UserServiceImpl(); //proxy class UserServiceProxy proxy = new UserServiceProxy(); //Use the agent class to realize the log function! proxy.setUserService(userService); proxy.add(); } } Copy code
OK, by now, there should be no problem with the agent mode. The key point is that you need to understand the idea; We have enhanced the original functions without changing the original code, which is the core idea of AOP [talk about AOP: vertical development, horizontal development]
9.4 dynamic agent
- The role of dynamic agent is the same as that of static agent
- The proxy class of dynamic proxy is generated dynamically The proxy class of static proxy is written in advance
- Dynamic agents are divided into two categories: one is interface based dynamic agents, and the other is class based dynamic agents
- Dynamic agent based on interface -- JDK dynamic agent
- Class based dynamic proxy -- cglib
- Now Java sist is used to generate dynamic proxy Baidu javasist
- We use the native code of JDK here. The rest is the same!
The dynamic Proxy of JDK needs to understand two core classes: InvocationHandler and Proxy. Open the JDK help document to see [InvocationHandler: call handler]
Object invoke(Object proxy, method method, Object[] args); //parameter //Proxy - the proxy instance that calls the method //Method - the method corresponds to the instance that invokes the interface method on the proxy instance. The declared class of the method object will be the continuation of the method declaration // Interface, which can be the super interface of the proxy interface of the proxy class inheriting the method. //args - array of objects containing method calls that pass the parameter values of the proxy instance, or null if the interface method has no parameters. original // The parameters of type are contained in an instance of the appropriate primitive wrapper class, such as Java Lang. integer or Java lang.Boolean Copy code
[Proxy: Proxy]
//Generate proxy class public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } Copy code
The code implements the abstract role and real role as before! Rent.java is an abstract role
//Abstract role: rent a house public interface Rent { public void rent(); } Copy code
Host.java is the real role
//Real role: landlord, the landlord wants to rent the house public class Host implements Rent{ public void rent() { System.out.println("House rental"); } } Copy code
ProxyInvocationHandler. java is the proxy role
public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent) { this.rent = rent; } //Generate an agent class, focusing on the second parameter to obtain the abstract role to be represented! It used to be a role, but now it can act as an agent Class role public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } // Proxy: proxy class method: the method object of the calling handler of the proxy class // Process method calls on proxy instances and return results @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { seeHouse(); //Core: essence is realized by reflection! Object result = method.invoke(rent, args); fare(); return result; } //House viewing public void seeHouse(){ System.out.println("Show the tenant"); } //Intermediary fee public void fare(){ System.out.println("Intermediary fee"); } } Copy code
Client.java
//tenant public class Client { public static void main(String[] args) { //Real role Host host = new Host(); //Call handler for proxy instance ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setRent(host); //Put the real character in! Rent proxy = (Rent)pih.getProxy(); //Dynamically generate the corresponding proxy class! proxy.rent(); } } Copy code
Core: a dynamic agent generally represents a certain type of business. A dynamic agent can represent multiple classes, and the agent is the interface!
9.5 deepening understanding
Let's use dynamic proxy to implement UserService written later! We can also write a general dynamic proxy implementation class! All proxy objects can be set to Object!
public class ProxyInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } //Generate proxy class public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } // Proxy: proxy class // Method: the method object of the calling handler of the proxy class public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String methodName){ System.out.println("Yes"+methodName+"method"); } } Copy code
Test!
public class Test { public static void main(String[] args) { //Real object UserServiceImpl userService = new UserServiceImpl(); //Call handler for proxy object ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(userService); //Sets the object to proxy UserService proxy = (UserService)pih.getProxy(); //Dynamically generate proxy class! proxy.delete(); } } Copy code
[test, add, delete, modify, query and view the results]
9.6 benefits of dynamic agent
It has all the static agents. It also has all the static agents that don't have!
- It can make our real role more pure Stop paying attention to some public things
- Public business is done by agents The division of business is realized,
- When the public business expands, it becomes more centralized and convenient
- A dynamic agent, generally acting for a certain kind of business
- A dynamic proxy can proxy multiple classes, and the proxy is the interface!
10,AOP
10.1 what is AOP
AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, which realizes the unified maintenance of program functions through precompiled mode and runtime dynamic agent. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can be used for all parts of business logic It can reduce the coupling between various parts of business logic, improve the reusability of programs, and improve the efficiency of development.
10.2 role of AOP in Spring
Provide declarative transactions; Allows you to customize the cut plane
- Crosscutting concerns: methods or functions that span multiple modules of an application. That is, it has nothing to do with our business logic, but we need
- The focus is crosscutting concerns. Such as logging, security, caching, transactions, etc
- ASPECT: a special object whose crosscutting concerns are modularized. That is, it is a class.
- Advice: the work that must be done in the aspect. That is, it is a method in the class.
- Target: the notified object.
- Proxy: an object created after notification is applied to the target object.
- PointCut: the definition of the "place" where the aspect notification is executed.
- Join point: the execution point that matches the pointcut.
In spring AOP, crosscutting logic is defined through Advice. Spring supports five types of Advice:
That is, Aop adds new functions without changing the original code.
10.3 using Spring to implement Aop
[key] to use AOP weaving, you need to import a dependency package!
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> Copy code
The first way
Through the Spring API implementation, we first write our business interface and implementation class
public interface UserService { public void add(); public void delete(); public void update(); public void search(); } Copy code
public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("Add user"); } @Override public void delete() { System.out.println("delete user"); } @Override public void update() { System.out.println("Update user"); } @Override public void search() { System.out.println("Query user"); } } Copy code
Then write our enhancement class. We write two, one pre enhancement and one post enhancement
public class Log implements MethodBeforeAdvice { //Method: the method of the target object to execute //objects: parameters of the called method //Object: target object @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println( o.getClass().getName() + "of" + method.getName() + "Method was executed"); } } Copy code
public class AfterLog implements AfterReturningAdvice { //returnValue return value //Method called method //args parameter of the object of the called method //Target the called target object @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("Yes" + target.getClass().getName() +"of"+method.getName()+"method," +"Return value:"+returnValue); } } Copy code
Finally, register in the spring file and implement aop cut in implementation. Pay attention to import constraints
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" 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"> <!--register bean--> <bean id="userService" class="com.kuang.service.UserServiceImpl"/> <bean id="log" class="com.kuang.log.Log"/> <bean id="afterLog" class="com.kuang.log.AfterLog"/> <!--aop Configuration of--> <aop:config> <!--breakthrough point expression:The expression matches the method to execute--> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--Perform wrap; advice-ref Execution method . pointcut-ref breakthrough point--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans> Copy code
test
public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) context.getBean("userService"); userService.search(); } } Copy code
The importance of Aop: very important. We must understand the ideas, mainly the understanding of ideas
Spring's Aop combines public business (logging, security, etc.) with domain business. When implementing domain business, public business will be added Realize the reuse of public business The domain business is more pure. The program ape focuses on the domain business, and its essence is dynamic agent
The second way
Custom classes to implement Aop
The target business class remains the same as userServiceImpl
Step 1: write our own cut in class
public class DiyPointcut { public void before(){ System.out.println("---------Before method execution---------"); } public void after(){ System.out.println("---------After method execution---------"); } } Copy code
To configure in spring
<!--The second way is to customize the implementation--> <!--register bean--> <bean id="diy" class="com.kuang.config.DiyPointcut"/> <!--aop Configuration of--> <aop:config> <!--The second way: use AOP Label Implementation of--> <aop:aspect ref="diy"> <aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <aop:before pointcut-ref="diyPonitcut" method="before"/> <aop:after pointcut-ref="diyPonitcut" method="after"/> </aop:aspect> </aop:config> Copy code
Test:
public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } } Copy code
The third way
Implementation using annotations
Step 1: write an enhanced class for annotation implementation
package com.angus.config; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class AnnotationPointcut { @Before("execution(* com.angus.service.UserServiceImpl.*(..))") public void before(){ System.out.println("---------Before method execution---------"); } @After("execution(* com.angus.service.UserServiceImpl.*(..))") public void after(){ System.out.println("---------After method execution---------"); } @Around("execution(* com.angus.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("Surround front"); System.out.println("autograph:"+jp.getSignature()); //Execute target method Object proceed = jp.proceed(); System.out.println("After surround"); System.out.println(proceed); } } Copy code
Step 2: register the bean in the Spring configuration file and add the configuration supporting annotation
<!--The third way:Annotation implementation--> <bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/> <aop:aspectj-autoproxy/> Copy code
AOP: AspectJ AutoProxy: description
adopt aop Namespace<aop:aspectj-autoproxy />Declaration is automatically spring Which configurations are in the container@aspectJ section of bean Create a proxy and weave in the cut. of course, spring It is still used internally AnnotationAwareAspectJAutoProxyCreator The creation of automatic agent has been carried out, but the details of the specific implementation have been <aop:aspectj-autoproxy />Hidden. <aop:aspectj-autoproxy />There is one proxy-target-class Property, default to false,Indicates use jdk dynamic Agent weaving enhancement when configured as<aop:aspectj-autoproxy poxy-target-class="true"/>When, it means to use CGLib Dynamic agent technology weaving enhancement. But even if proxy-target-class Set to false,If the target class does not declare Mouth, then spring Will be used automatically CGLib Dynamic proxy. Copy code
11. Integrate Mybatis
Steps:
- Import related jar packages
- junit
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> Copy code
- mybatis
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> Copy code
- mysql-connector-java
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> Copy code
- spring related
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.10.RELEASE</version> </dependency> Copy code
- aspectJ AOP Weaver
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> Copy code
- Mybatis spring integration package [key]
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> Copy code
- Configure Maven static resource filtering problem!
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build> Copy code
- Write configuration file
- code implementation
Recall MyBatis
Writing pojo entity classes
package com.kuang.pojo; public class User { private int id; //id private String name; //full name private String pwd; //password } Copy code
Configuration file for implementing mybatis
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.kuang.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <package name="com.kuang.dao"/> </mappers> </configuration> Copy code
Written by UserDao interface
public interface UserMapper { public List<User> selectUser(); } Copy code
Mapper mapping file corresponding to interface
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.kuang.dao.UserMapper"> <select id="selectUser" resultType="User"> select * from user </select> </mapper> Copy code
Test class
@Test public void selectUser() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.selectUser(); for (User user: userList){ System.out.println(user); } sqlSession.close(); } Copy code
Mybatis spring learning
Before introducing Spring, you need to understand some important classes in the mybatis Spring package; www.mybatis.org/spring/zh/i...
What is mybatis spring?
MyBatis Spring will help you seamlessly integrate MyBatis code into Spring.
Knowledge base before you start using MyBatis Spring, you need to be familiar with the two frameworks Spring and MyBatis and their terms. This is important.
Mybatis spring requires the following versions:
If you use Maven as a build tool, you only need to use it in POM Add the following code to XML:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> Copy code
To use MyBatis with Spring, you need to define at least two things in the Spring application context: a SqlSessionFactory and at least one data mapper class. In MyBatis Spring, SqlSessionFactory bean can be used to create SqlSessionFactory. To configure this factory bean, you only need to put the following code in the XML configuration file of Spring:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> </bean> Copy code
Note: SqlSessionFactory requires a DataSource (data source). This can be any DataSource. You only need to configure it as other Spring database connections. In the basic MyBatis usage, SqlSessionFactory is created through SqlSessionFactoryBuilder. In MyBatis Spring, SqlSessionFactoryBean is used.
In MyBatis, you can use SqlSessionFactory to create sqlsessions. Once you get a session, you can use it to execute mapped statements, commit or rollback connections, and finally close the session when it is no longer needed.
SqlSessionFactory has a unique required property: DataSource for JDBC. This can be any DataSource object, and its configuration method is the same as that of other Spring database connections.
A common attribute is configLocation, which is used to specify the XML configuration file path of MyBatis. It is very useful when you need to modify the basic configuration of MyBatis. Generally, the basic configuration refers to < Settings > or < typealiases > elements. It should be noted that this configuration file does not need to be a complete MyBatis configuration. Specifically, any Environment configuration (< environments >), data source (< datasource >) and MyBatis transaction manager (< transactionmanager >) will be ignored. SqlSessionFactoryBean will create its own MyBatis Environment configuration (Environment) and set the value of custom Environment as required.
SqlSessionTemplate is the core of mybatis spring. As an implementation of SqlSession, this means that it can be used to seamlessly replace the SqlSession already in use in your code.
Templates can participate in Spring's transaction management, and because they are thread safe, they can be used by multiple mapper classes. You should always use SqlSessionTemplate to replace the default DefaultSqlSession implementation of MyBatis. Mixing different classes in the same application may cause data consistency problems. You can use SqlSessionFactory as a parameter of the construction method to create a SqlSessionTemplate object.
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean> Copy code
Now, this bean can be directly injected into your DAO bean. You need to add a SqlSession attribute to your bean, as follows:
public class UserDaoImpl implements UserDao { private SqlSession sqlSession; public void setSqlSession(SqlSession sqlSession) { this.sqlSession = sqlSession; } public User getUser(String userId) { return sqlSession.getMapper...; } } Copy code
Inject SqlSessionTemplate as follows:
<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl"> <property name="sqlSession" ref="sqlSession" /> </bean> Copy code
Integration implementation I
- Introduce the Spring configuration file beans 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> Copy code
- Configure the data source to replace the data source of mybaits
<!--Configure data sources: there are many data sources. You can use third-party or Spring of--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis? useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> Copy code
- Configure SqlSessionFactory and associate MyBatis
<!--to configure SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--relation Mybatis--> <property name="configLocation" value="classpath:mybatis- config.xml"/> <property name="mapperLocations" value="classpath:com/kuang/dao/*.xml"/> </bean> Copy code
- Register sqlSessionTemplate and associate sqlSessionFactory;
<!--register sqlSessionTemplate , relation sqlSessionFactory--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--Using constructor injection--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> Copy code
- Add the implementation class of Dao interface; Privatize sqlSessionTemplate
public class UserDaoImpl implements UserMapper { //sqlSession does not need to be created by ourselves, but managed by Spring private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } } Copy code
- Register bean implementation
<bean id="userDao" class="com.kuang.dao.UserDaoImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> Copy code
- test
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); } Copy code
The result is output successfully! Now the status of our Mybatis configuration file! Discovery can be integrated by Spring!
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.kuang.pojo"/> </typeAliases> </configuration> Copy code
Integration implementation II
mybatis-spring1. Only those above version 2.3 have this Screenshot of official document: dao inherits the Support class, obtains it directly using getSqlSession(), and then injects it directly into SqlSessionFactory Compared with mode 1, there is no need to manage SqlSessionTemplate, and the Support for transactions is more friendly Traceable source code view
Test:
- Modify the UserDaoImpl we wrote above
public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.selectUser(); } } Copy code
- Modify bean configuration
<bean id="userDao" class="com.kuang.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> Copy code
- test
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); } Copy code
Conclusion: after integration into spring, we can completely eliminate the configuration file of mybatis. In addition to these methods, we can also use annotations to realize the integration. This will be tested when we learn about SpringBoot later!
12. Declarative transaction
12.1 review
- Transaction is very important in the project development process. It involves the problem of data consistency, which should not be careless!
- Transaction management is a necessary technology in enterprise application development to ensure data integrity and consistency.
Transaction is to treat a series of actions as an independent unit of work, which are either completed or ineffective.
Transaction four attribute ACID
- atomicity
- A transaction is an atomic operation, which consists of a series of actions. The atomicity of a transaction ensures that the actions either complete or fail to work at all
- consistency
- Once all transaction actions are completed, the transaction is committed. Data and resources are in a consistent state that meets business rules
- isolation
- Multiple transactions may process the same data at the same time, so each transaction should be isolated from other transactions to prevent data corruption
- Persistence
- Once the transaction is completed, no matter what error occurs in the system, the result will not be affected. Typically, the result of a transaction is written to persistent storage
12.2 test
Copy the above code to a new project. In the previous case, we added two methods to the userDao interface, delete and add users;
//Add a user int addUser(User user); //Delete user by id int deleteUser(int id); Copy code
mapper file, we deliberately write delete wrong, test!
<insert id="addUser" parameterType="com.kuang.pojo.User"> insert into user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <delete id="deleteUser" parameterType="int"> deletes from user where id = #{id} </delete> Copy code
Write the implementation class of the interface. In the implementation class, we operate a wave
public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper { //Add some operations public List<User> selectUser() { User user = new User(4,"Xiao Ming","123456"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(4); return mapper.selectUser(); } //newly added public int addUser(User user) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.addUser(user); } //delete public int deleteUser(int id) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.deleteUser(id); } } Copy code
test
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); } Copy code
Error reporting: sql exception. delete is written incorrectly
Result: insertion succeeded!
No transaction management; We want them to succeed only when they succeed. If there is a failure, they will all fail. We should need affairs!
In the past, we all needed to manage affairs manually, which was very troublesome!
However, Spring provides us with transaction management, and we only need to configure it;
12.3 transaction management in Spring
Spring defines an abstraction layer on top of different transaction management APIs, so that developers can use spring's transaction management mechanism without understanding the underlying transaction management API. Spring supports programmatic transaction management and declarative transaction management.
Programming transaction management
- Embed transaction management code into business methods to control transaction commit and rollback
- Disadvantages: additional transaction management code must be included in each transaction operation business logic
Declarative transaction management
- Generally, it works better than programmatic transactions.
- The transaction management code is separated from the business method to realize the transaction management in a declarative way.
- Transaction management is regarded as a crosscutting concern and modularized through aop method. Spring supports declarative transaction management through the Spring AOP framework
Using Spring to manage transactions, pay attention to the constraint import of header file: tx
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> Copy code
Transaction manager
- No matter which transaction management strategy (programmatic or declarative) Spring uses, the transaction manager is required.
- Spring's core transaction management abstraction encapsulates a set of technology independent methods.
JDBC transaction
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> Copy code
After configuring the transaction manager, we need to configure the notification of transactions
<!--Configure transaction notifications--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--What methods are configured and what transactions are used,Configure propagation properties of transactions--> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="search*" propagation="REQUIRED"/> <tx:method name="get" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> Copy code
spring transaction propagation feature: transaction propagation behavior is how transactions propagate among multiple transaction methods when they call each other. spring supports seven transaction propagation behaviors:
- propagation_requierd: if there is no transaction at present, create a new transaction. If there is already a transaction, join it
This is the most common choice of transactions.
- propagation_supports: supports the current transaction. If there is no current transaction, it will be executed in a non transaction method.
- propagation_mandatory: use the current transaction. If there is no current transaction, an exception will be thrown.
- propagation_required_new: create a new transaction. If there is a current transaction, suspend the current transaction.
- propagation_not_supported: perform operations in a non transactional manner. If there is a transaction, suspend the current transaction.
- propagation_never: execute the operation in a non transactional manner. If the current transaction exists, an exception will be thrown.
- propagation_nested: if a transaction currently exists, it is executed within a nested transaction. If there are currently no transactions, execute and
- propagation_required similar operations
The default transaction propagation behavior of Spring is PROPAGATION_REQUIRED, which is suitable for most situations.
Assuming that ServiveX#methodX() works in a transaction environment (that is, they are enhanced by Spring transactions), assuming that there is the following call chain in the program: service1 #method1 () - > service2 #method2 () - > service3 #method3 (), then the three methods of the three service classes work in the same transaction through the transaction propagation mechanism of Spring.
For example, the methods we just mentioned are called, so they will be placed in a group of transactions!
Configure the header file of aop import!
<!--to configure aop Weaving transaction--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.kuang.dao.*.* (..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config> Copy code
Test, delete the data just inserted, and test again!
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); } Copy code
Thinking?
Why do I need to configure transactions?
- If it is not configured, we need to manually submit the control transaction;
- Transaction is very important in the project development process. It involves the problem of data consistency, which should not be careless!
Author: angus_study
Link: https://juejin.cn/post/7041092696567447589