Spring
1.1 INTRODUCTION
-
Spring: Spring ------ > brings spring to the software industry
-
In 2002, the prototype of spring framework, interfaace21 framework, was launched for the first time
-
Spring framework is based on interface21 framework. After redesign and constantly enriching its connotation, it released the official version of 1.0 on March 24, 2004
-
Rod Johnson, founder and famous author of Spring Framework. It's hard to imagine that rod Johnson's degree really surprised many people. He is a doctor at the University of Sydney. However, his major is not computer, but musicology.
-
Spring concept: make the existing technology easier to use. It is a hodgepodge and integrates the existing technology framework!
-
SSH: Struct2 + Spring + Hibernate!
-
SSM: SpringMVC + Spring + Mybatis!
Official website: https://spring.io/projects/spring-framework#overview
Official download address: https://repo.spring.io/release/org/springframework/spring/
GitHub: https://github.com/spring-projects/spring-framework
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <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>
1.2 advantages
- Spring is an open source, free framework (container)
- spring is a lightweight, non intrusive framework!
- Inversion of control (IOC) and aspect oriented programming (AOP)
- Support transaction processing and framework integration!
Summary: spring is a lightweight control inversion (IOC) and aspect oriented programming (AOP) framework
1.3 composition of Spring
1.4 expansion
Modern Java development is spring based development
- spring boot
- A rapid development of scaffolding!
- Based on spring boot, a single microservice can be developed quickly
- Contract greater than configuration
- spring cloud
- Spring cloud is implemented based on spring boot
Because most companies are now using springboot for rapid development, the premise of learning springboot is to fully master spring and springMVC! Connecting role
Disadvantages: after development for too long, it violates the original concept, and the configuration is very cumbersome, which is called configuration hell.
2. IOC theoretical derivation
-
1. Write UserDao interface
package com.kuang.dao; public interface UserDao { void getUser(); }
-
2. Write UserDao interface implementation class
package com.kuang.dao; public class UserDaoImpl implements UserDao { public void getUser() { System.out.println("Get user data by default"); } }
-
3. Write UserService business interface
package com.kuang.service; public interface UserService { void getUser(); }
-
4. Write UserService business interface implementation class
package com.kuang.service; import com.kuang.dao.UserDao; import com.kuang.dao.UserDaoImpl; public class UserServiceImpl implements UserService { private UserDao userDao ; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void getUser() { userDao.getUser(); } }
-
5. Testing
import com.kuang.dao.UserDao; import com.kuang.dao.UserDaoImpl; import com.kuang.dao.UserMysqlImpl; import com.kuang.service.UserServiceImpl; public class MyTest { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(new UserMysqlImpl()); userService.setUserDao(new UserDaoImpl()); userService.getUser() ; } }
In our previous business, the needs of users may affect our original code. We need to modify the source code according to the needs of users. If the amount of program code is very large, the cost of modification is very expensive.
We use a set interface implementation, which has undergone revolutionary changes
private UserDao userDao; //Use set to dynamically realize value injection! public void setUserDao(UserDao userDao) { this.userDao = userDao; }
- Previously, the program was created actively, and the control was in the hands of the programmer.
- After using set injection, the program is no longer active, but becomes a passive receiving object.
This idea essentially solves the problem. We programmers don't have to manage the creation of objects anymore. I love you. The coupling of the system is greatly reduced, and you can focus more on the implementation of business. This is the prototype of IOC.
The essence of IOC:
- Control inversion IOC is a design idea, and DI dependency injection is a method to realize IOC.
- Others say that everyone for DI is just another way of saying IOC. In programs without IOC, we use object-oriented programming. The creation of objects is completely hard coded in the program. 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, that is, the spring container. Personally, the so-called inversion of control is that the way to obtain dependent objects is reversed
- When configuring beans with xml, the bean definition information is separated from the implementation, and the two can be combined by annotation. The bean definition information is directly defined in the implementation class in the form of annotation, so as to achieve the purpose of zero configuration.
- Inversion of control is a way to create or obtain specific objects through xml or annotations and through a third party. The IOC container implements control inversion in spring, and its implementation method is DI dependency injection.
3,HelloSpring
1. Create a maven project and write entity classes
package com.kuang.pojo; public class Hello { private String str; public Hello(String str) { this.str = str; } public Hello() { } public String getStr() { return str; } public void setStr(String str) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\'' + '}'; } }
2. Writing xml 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 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.kuang.pojo.Hello"> <property name="str" value="hello,spring"/> </bean> </beans>
3. Testing
public class MyTest { public static void main(String[] args) { //Get the context object of Spring! ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //Our objects are now managed in Spring. We need to use them. Just take them out! Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
Thinking questions:
- 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 IOC control inversion:
- **Control: * * who controls the creation of objects? Objects in traditional applications 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: * * is injected using the set method
IOC is a programming idea, from active programming to passive reception.
You can browse the source code through the new ClassPathXMLApplicationContext.
OK, up to now, 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: objects are created, managed and assembled by Spring!
4. How IOC creates bean s (objects)
-
1. Create objects using parameterless construction, default.
-
2. Suppose we want to create objects using parametric construction, there are three ways
-
1. Subscript assignment
-
<!--The first method: subscript assignment --> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg index="0" value="Madness theory Java"/> </bean>
-
2. Type
<!--The second method is to create a type. It is not recommended --> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg type="java.lang.String" value="lifa"/> </bean>
-
3. According to parameter name
-
<!--The third method: set directly through the parameter name --> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg name="name" value="Li Fa"/> </bean>
-
Summary: when the configuration file is loaded, the objects managed in the container have been initialized!
5. spring configuration
5.1 alias
<!--Alias. If an alias is added, we can also use the alias to get this object--> <alias name="user" alias="userNew"/>
5.2 Bean configuration
<!-- id: bean The unique identifier of, which is equivalent to the object name we learned class: bean Fully qualified name corresponding to the object: package name+Class name name: It's also an alias, and name Multiple aliases can be taken at the same time --> <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3;u4"> <property name="name" value="Black heart white lotus"/> </bean>
5.3,import
This import is generally used for team development. It can import and merge multiple configuration files into one.
Suppose that there are many individual developers in the project. These three people are responsible for the development of different classes. Different classes need to be registered in different beans. We can use import to import everyone's beans XML is merged into a total
-
Zhang San
-
Li Si
-
Wang Wu
-
ApplicationContext.xml
<import resource="bean.xml"/> <import resource="bean2.xml"/> <import resource="bean3.xml"/>
When using, just use the general configuration directly
6. Dependency injection
6.1. Constructor injection
As described earlier, refer to 4. How IOC creates objects
6.2 Set method injection [ key ]
- Dependency injection: set injection
- Dependency: the creation of bean objects depends on the container
- Injection: all attributes in the bean object are injected by a container
[environment matching]
-
1. Complex type
package com.kuang.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
2. Real test type
package com.kuang.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> hobbies; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public List<String> getHobbies() { return hobbies; } public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } }
-
3,applicationContext.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"> <bean id="name" class="com.kuang.pojo.Student"> <property name="name" value="Qin Jiang"></property> </bean> </beans>
-
4. Testing
import com.kuang.pojo.Student; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student name = (Student) context.getBean("name"); System.out.println(name.getName()); } }
-
5. Perfect injection information
<bean id="address" class="com.kuang.pojo.Address"> <property name="address" value="Xi'an"></property> </bean> <bean id="name" class="com.kuang.pojo.Student"> <property name="name" value="Qin Jiang"></property> <property name="address" ref="address"/> <property name="books" > <array> <value>Journey to the West</value> <value>Romance of the Three Kingdoms</value> <value>Water Margin</value> </array> </property> <property name="hobbies"> <list> <value>read a book</value> <value>listen to the music</value> <value>watch movie</value> <value>play with the smarthphone</value> </list> </property> <property name="card"> <map> <entry key="ID number" value="111111222222333333"></entry> <entry key="bank card" value="512345156663322"></entry> </map> </property> <property name="games"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property> <property name="wife"> <null/> </property> <property name="info"> <props> <prop key="Student number">123456</prop> <prop key="url">123456</prop> <prop key="root">root</prop> <prop key="password">123456</prop> </props> </property> </bean>
6.3 expand injection mode
We use the p namespace and the c namespace for injection.
Official interpretation:
use
<?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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--p Namespace injection, you can directly inject the value of the attribute: property--> <bean id="user" class="com.kuang.pojo.User" p:name="Black heart white lotus" p:age="20"/> <!--c Namespace injection through constructor: constructor-args--> <bean id="user2" class="com.kuang.pojo.User" c:name="Mad God" c:age="22"/> </beans>
Test:
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = context.getBean("user",User.class); System.out.println(user); User user2 = context.getBean("user2",User.class); System.out.println(user2); }
Note: the p naming and c namespace cannot be used directly. You need to import xml constraints!
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
6.4 scope of bean
1. Singleton mode (spring default mechanism)
<bean id="user2" class="com.kuang.pojo.User" c:name="Mad God" c:age="22" scope="singleton"/>
2. Prototype pattern: each time you get from the container, a new object will be generated
<bean id="user2" class="com.kuang.pojo.User" c:name="Mad God" c:age="22" scope="prototype"/>
3. Other request s, session s, and application s can only be used in the web.
7. Automatic assembly of Bean
- Automatic assembly is a way for spring to meet bean dependencies!
- spring will automatically find in the context and automatically assemble properties for the bean
Three assembly methods in spring:
- Configuration displayed in xml
- Display configuration in Java;
- Implicit automatic assembly bean [key]
7.1 test
Environment matching: create a project where one person has two pets.
<bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="people" class="com.kuang.pojo.People"> <property name="name" value="Qin Jiang"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean>
7.2 ByName automatic assembly
<!-- byName: It will automatically find its own objects in the container context set Method bean id! --> <bean id="people" class="com.kuang.pojo.People" autowire="byName"> <property name="name" value="Qin Jiang"/> </bean>
7.3 ByType automatic assembly
<!-- byType: It will automatically find the object with the same property type as its own object in the container context bean! --> <bean id="people" class="com.kuang.pojo.People" autowire="byType"> <property name="name" value="Qin Jiang"/> </bean>
Summary:
- When ByName, it is necessary to ensure that the IDs of all beans are unique, and the bean needs to be consistent with the value of the set method of the automatically injected attribute.
- When ByType, it is necessary to ensure that the class of all beans is unique, and the bean needs to be consistent with the type of automatically injected properties.
7.4. Use notes to realize automatic assembly
jdk1.5 supported annotations, spring 2 5 supports annotation
To use notes:
-
Import constraints
-
Configuration annotation support
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--Enable annotation support --> <context:annotation-config/> </beans>
-
@Autowired
- It can be used directly on attributes or set methods.
- Using Autowired, we don't need to write the set method. The premise is that your auto assembled attribute exists in the IOC container and conforms to the name ByName!
-
polular science:
@Nullable The field is marked with this annotation, indicating that this field can be null;
public @interface Autowired { boolean required() default true; }
-
Test code
public class People { //If the required property of Autowired is explicitly defined as false, it means that the object can be null, otherwise it is not allowed to be empty @Autowired(required = false) private Cat cat; @Autowired private Dog dog; private String name; }
If the environment of @ Autowired auto assembly is complex and the auto assembly cannot be completed through an annotation, we can use @ Qualifier(value = "xxx") to configure the use of @ Autowired * * and specify a unique bean object injection**
public class People { @Autowired @Qualifier(value = "cat111") private Cat cat; @Autowired @Qualifier(value = "dog222") private Dog dog; private String name; }
@Resource
public class People { @Resource private Cat cat; @Resource private Dog dog; }
Summary:
@Difference between Resource and @ Autowired:
- They are used for automatic assembly and can be used in attribute fields.
- @Autowired is implemented by ByType, and this object must exist.
- @Resource is implemented by ByName by default. If the name cannot be found, it is implemented by ByType. If both cannot be found, an error is reported.
- Different execution order: @ Autowired is implemented by byType.
8. Using annotation development
After spring 4, if you want to develop with annotations, you must ensure that the aop package is imported
You need to import constraints to use annotations, and configure annotation support!
<?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 https://www.springframework.org/schema/context/spring-context.xsd"> <!--Enable annotation support --> <context:annotation-config/> </beans>
- bean
- How attributes are injected
//Equivalent to < bean id = "user" class = "com. Kuang. POJO. User" / > //@Component component @Component public class User { //Equivalent to < property name = "name" value = "white lotus" / > @Value("White lotus") public String name; }
3. Derived notes
@Component has several derived annotations. In web development, we will layer according to mvc three-tier architecture!
dao [@Repository] service [@Service] controller [@Controller]
The four annotation functions are the same. They all represent registering a class in Spring and assembling beans
4. Automatic assembly
- @Autowired: auto assembly type and name. If Autowired cannot uniquely and automatically assemble attributes, it needs to be configured through @ Qualifier(value = "xxx").
- @The Nullable field is marked with this annotation, indicating that this field can be null;
- @Resource: name and type of automatic assembly.
5. Scope
@Component @Scope("singleton") public class User { //Equivalent to < property name = "name" value = "white lotus" / > @Value("White lotus") public String name; }
6. Summary:
xml and annotations:
- xml is more versatile and suitable for any occasion! Simple and convenient maintenance
- Annotations are not their own class. They can't be used. Maintaining the phase team is complex!
- xml and annotation best practices:
- xml is used to manage bean s;
- Annotation is only responsible for completing attribute injection;
- In the process of using, we only need to pay attention to one problem: to make the annotation effective, we need to turn on the annotation support
<!--Specify the package to be scanned, and the annotations under the package will take effect--> <context:component-scan base-package="com.kuang"/> <!--Enable annotation support --> <context:annotation-config/>
9. Configure Spring in a pure java way
We will not use the xml configuration of Spring at all now, and leave it to Java!
JavaConfig is a sub project of Spring. After Spring 4, it has become a core function!
Entity class
//The annotation here means that this class is taken over by Spring and registered in the container @Component public class User { private String name; public String getName() { return name; } @Value("Black heart white lotus") //Attribute injection value public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }
configuration file
// This will also be managed by the Spring container and registered in the container, because it is originally a @ Component // @Configuration means that this is a configuration class, just like the beans xml @Configuration @ComponentScan("com.kuang.pojo") @Import(KuangConfig2.class) public class KuangConfig { // Registering a bean is equivalent to a bean tag we wrote earlier // The name of this method is equivalent to the id attribute in the bean tag // The return value of this method is equivalent to the class attribute in the bean tag @Bean public User user(){ return new User(); // Is to return the object to be injected into the bean! } }
Test class
public class MyTest { public static void main(String[] args) { //If the configuration class method is completely used, we can only obtain the container through the AnnotationConfig context and load it through the class object of the configuration class! ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class); User user = context.getBean("user", User.class); System.out.println(user.getName()); } }
This pure Java configuration method can be seen everywhere in SpringBoot!
10. Agent mode
Why learn agent mode? Because this is the bottom of AOP! [spring aop and spring MVC]
Classification of agent mode:
- Static proxy
- Dynamic agent
10.1 static agent
Role analysis:
- Abstract role: it is usually solved by using interfaces or abstract classes
- Real role: the role represented
- Agent role: represent the real role. After representing the real role, we usually do some ancillary operations.
- Customer: the person who accesses the proxy object!
Code steps:
1. Interface [Abstract role]
package com.kuang.dao; //Rental, abstract role public interface Rent { public void rent(); }
2. Real role
package com.kuang.dao; //Landlord, I want to rent the house public class Host implements Rent { public void rent() { System.out.println("I'm going to rent the house"); } }
3. Agent role
package com.kuang.dao; //delegable role public class Proxy implements Rent { private Host host; public Proxy(Host host) { this.host = host; } public Proxy() { } public void rent() { host.rent(); seeHost(); heTong(); fare(); } public void seeHost(){ System.out.println("Intermediary look at the house"); } public void heTong(){ System.out.println("sign a contract"); } public void fare(){ System.out.println("Intermediary fee"); } }
4. Client access agent role
public class Client { public static void main(String[] args) { //The landlord wants to rent the house Host host = new Host(); // host.rent(); //Agent, the intermediary helps the landlord rent the house, and the agent role generally has some ancillary operations! Proxy proxy = new Proxy(host); //Do not face the landlord, directly find an intermediary to rent a house! proxy.rent(); } }
Benefits of agent mode:
- It can make the operation of real characters more pure! Don't pay attention to some public business
- The public role will be handed over to the agent role! The division of business is realized
- When the public business is expanded, it is convenient for centralized management
Disadvantages:
- A real role will produce a proxy role, the amount of code will double, and the development efficiency will be low.
10.2 deepen understanding
Code operation steps:
1. Interface
public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
2. Real role
//Real role public class UserServiceImpl implements UserService{ public void add() { System.out.println("Added a user!"); } public void delete() { System.out.println("Deleted a user!"); } public void update() { System.out.println("Modified a user!"); } public void query() { System.out.println("Queried a user!"); } }
3. Agent role
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("[Debug] One was used"+msg+"method"); } }
4. Customer access agent role
public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); proxy.setUserService(userService); proxy.delete(); } }
Talk about AOP
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-jvlch8ui-1639549827919) (C: \ users \ Dell \ appdata \ roaming \ typora \ typora user images \ image-20211211143403790. PNG)]
10.3 dynamic agent
- Dynamic agents have the same role as static agents
- The agent class of dynamic agent is dynamically generated, which is not written directly.
- Dynamic agents are divided into two categories: interface based dynamic agents [jdk] and class based dynamic agents [cglib]
- Interface based: JDK dynamic agent [we use it here]
- Class based: cglib
- java bytecode implementation: javassist
You need to understand two classes: Proxy: Proxy; InvocationHandler: call handler;
Code steps:
-
Interface
package com.kuang.demo01; //Rental, abstract role public interface Rent { public void rent(); }
-
Real role
package com.kuang.demo01; //Landlord, I want to rent the house public class Host implements Rent { public void rent() { System.out.println("I'm going to rent the house"); } }
-
ProxyInvocationHandler class
package com.kuang.demo01; import org.aopalliance.intercept.Invocation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //We will use this class to automatically generate proxy classes public class ProxyInvocationHandler implements InvocationHandler { //Proxy interface private Rent rent; public void setRent(Rent rent) { this.rent = rent; } /* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class } ,handler); * */ //Generate proxy class public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } //Process the proxy instance and return the result public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //The essence of dynamic proxy mechanism is reflection mechanism Object relust = method.invoke(rent, args); seeHost(); return relust; } public void seeHost(){ System.out.println("The agent showed me the house"); } }
-
test
package com.kuang.demo01; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { //Real role Host host = new Host(); //The agent role does not exist now. Do you want to generate it automatically ProxyInvocationHandler pih = new ProxyInvocationHandler(); //Handle the interface object we want to call by calling the program processing role! pih.setRent(host); Rent proxy= (Rent) pih.getProxy();//Proxy is an automatically generated proxy class, which is not written by us proxy.rent(); } }
Here, we can extract ProxyInvocationHandler as a tool class
//Use this class to automatically generate proxy classes! public class ProxyInvocationHandler implements InvocationHandler { //Proxy interface private Object target; public void setTarget(Object target) { this.target = target; } //Generated proxy class public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } //Process the proxy instance and return the result 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 msg){ System.out.println("[Debug] One was used"+msg+"method"); } }
Benefits of dynamic agents:
- It can make the operation of real characters more pure! Don't pay attention to some public business
- The public role will be handed over to the agent role! Realize the division of business!
- When the public business is expanded, it is convenient for centralized management!
- A dynamic proxy class is an interface, which is generally the corresponding type of business.
- A dynamic proxy class can proxy multiple classes as long as it implements the same interface.
11,AOP
11.2 what is AOP
AOP: 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 and an important content in spring framework. It is a derivative generic of functional programming. Using AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program and improve the efficiency of development.
11.2 role of AOP in spring
Provide declarative transactions: allow users to customize aspects
-
Crosscutting concerns: methods or functions that span multiple modules of an application; That is, the crosscutting concerns are those that have nothing to do with our business logic, but we need to focus on. Such as log, security, cache, transaction, 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.
11.3. Using spring to realize 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>
**Method 1: * * use spring API interface [mainly spring API interface implementation]
-
1. Under service package, define UserService business interface and UserServiceImpl implementation class
public interface UserService { public void add(); public void delete(); public void update(); public void select(); }
public class UserServiceImpl implements UserService { public void add() { System.out.println("Added a user!"); } public void delete() { System.out.println("Deleted a user!"); } public void update() { System.out.println("Updated a user!"); } public void select() { System.out.println("Queried a user!"); } }
-
2. Under the log package, we define our enhancement classes, a log pre enhancement class and an afterlog post enhancement class
public class Log implements MethodBeforeAdvice { //Method: the method of the target object to execute //args: parameter //Target: target object public void before(Method method, Object[] agrs, Object target) throws Throwable { System.out.println(target.getClass().getName()+"of"+method.getName()+"Executed"); } }
public class AfterLog implements AfterReturningAdvice { //returnValue: return value public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("Yes"+method.getName()+"Method, the return result is:"+returnValue); } }
-
3. Finally, register in the spring configuration file and implement AOP cut in implementation. Pay attention to import constraints and configure ApplicationContext XML file
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://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"/> <!--Method 1: use native Spring API Interface--> <!--to configure aop:Import required aop Constraints of--> <aop:config> <!--Entry point: expression: expression, execution(Location to execute!* * * * *)--> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--Execute surround increase!--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
-
4. Testing
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //Dynamic proxy interface: Note UserService userService = (UserService) context.getBean("userService"); userService.add(); // userService.select(); } }
**Method 2: * * user defined classes to implement AOP [mainly section definitions]
-
1. Define your own DiyPointCut cut in class under the diy package
public class DiyPointCut { public void before(){ System.out.println("======Before method execution======"); } public void after(){ System.out.println("======After method execution======"); } }
-
2. Go to the configuration file in spring
<!--Method 2: user defined class--> <bean id="diy" class="com.kuang.diy.DiyPointCut"/> <aop:config> <!--Custom cut, ref Class to reference--> <aop:aspect ref="diy"> <!--breakthrough point--> <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--notice--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
-
3. Testing
**Method 3: * * implemented with annotations!
-
1. Directly implemented AnnotationPointCut enhancement classes are defined under the diy package
//Declarative transaction! @Aspect //Label this class as a facet public class AnnotationPointCut { @Before("execution(* com.kuang.service.UserServiceImpl.*(..))") public void before(){ System.out.println("====Before method execution===="); } @After("execution(* com.kuang.service.UserServiceImpl.*(..))") public void after(){ System.out.println("====After method execution===="); } //In surround enhancement, we can give a parameter to represent the point where we want to get the processing entry point; @Around("execution(* com.kuang.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable{ System.out.println("Surround front"); Signature signature = jp.getSignature();// Get signature System.out.println("signature:"+signature); Object proceed = jp.proceed(); //Execution method System.out.println("After surround"); System.out.println(proceed); } }
-
2. In the spring configuration file, register bean s and add configurations that support annotations
<!--Method 3: use annotation--> <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/> <!--Enable annotation support! JDK(The default is proxy-target-class="false") cglib(proxy-target-class="true")--> <aop:aspectj-autoproxy/>
-
3. Testing
12. Integrate MyBatis
Steps:
-
1. Import related jar packages
- Junit
- mybatis
- MySQL
- spring related
- aop Weaver
- Mybatis spring integration package [key] import lombok package again
- Configure maven static resource filtering problem!
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <!--Spring If you operate the database, you also need one spring-jdbc --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </build>
-
2. Write configuration file
-
3. Testing
12.1. Recall MyBatis
-
1. Writing pojo entity classes
-
package com.kuang.pojo; public class User { private int id; private String name; private String pwd; public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public User() { } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
-
2. Write a configuration file to implement 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 core file--> <configuration> <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=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <package name="com.kuang.dao"></package> </mappers> </configuration>
-
3. Write UserMapper interface
-
package com.kuang.dao; import com.kuang.pojo.User; import java.util.List; public interface UserMapper { List<User> select(); }
-
4. Write usermapper XML file
-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--configuration core file--> <mapper namespace="com.kuang.dao.UserMapper"> <select id="select" resultType="com.kuang.pojo.User"> select * from mybatis.user </select> </mapper>
-
5. Testing
-
import com.kuang.dao.UserMapper; import com.kuang.pojo.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MyTest { @Test public void test() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(true); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> list = mapper.select(); for (User user : list) { System.out.println(user); } } }
12.2,MyBatis-spring
What is mybatis spring
Mybatis spring will help you seamlessly integrate mybatis code into spring.
Document link: http://mybatis.org/spring/zh/index.html
If you use Maven as a build tool, you only need to use it in POM Add the following code to XML:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency>
Integration to achieve one:
-
1. Introduce the spring configuration file spring Dao 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"> </beans>
-
2. Configure the data source to replace the data source of mybatis
-
<?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"> <!--DataSource:use Spring Data source replacement for Mybatis Configuration of c3p0 dbcp druid We use it here Spring Provided JDBC: --> <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=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> </beans>
-
3. Configure SQLSessionFactory and associate mybatis
-
<!--to configure SQLSessionFactory,relation 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"></property> </bean>
-
4. Register sqlsessionTemplate and associate SQLSessionFactory
-
<!--register sqlsessionTemplate,relation SQLSessionFactory--> <!--sqlsessionTemplate:That's what we used before SQLSession--> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <!--register sqlsessionTemplate,relation SQLSessionFactory--> <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg> </bean>
-
The UserMapperImpl implementation class of the UserMapper interface is required to privatize the sqlsessionTemplate
-
package com.kuang.dao; import com.kuang.pojo.User; import org.mybatis.spring.SqlSessionTemplate; import java.util.List; public class UserMapperImpl implements UserMapper { //All our operations are executed using sqlSession. In the past, SqlsessionTemplate is used now private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> select() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.select(); } }
-
6. Inject the implementation class you wrote into your spring configuration
-
<bean id="userMapper" class="com.kuang.dao.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"></property> </bean>
-
7. Test and use!
-
@Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList = userMapper.select(); for (User user : userList) { System.out.println(user); } }
Implementation mode 2:
mybatis-spring1. Only those above version 2.3 have this. Screenshot of official document:
dao inherits the Support class, obtains it directly by getSqlSession(), and then injects it directly into SqlSessionFactory Compared with integration mode 1, SqlSessionTemplate does not need to be managed, and the Support for transactions is more friendly Can track the source code to view.
Test:
-
Modify the UserMapperImpl we wrote above
-
public List<User> select() { return getSqlSession().getMapper(UserMapper.class).select(); }
-
Inject into the Spring configuration file.
-
<bean id="userMapper" class="com.kuang.dao.UserMapperImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
-
test
-
@Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList = userMapper.select(); for (User user : userList) { System.out.println(user); } }
13. Declarative transaction
13.1 review
- Treat a group of businesses as one business, and either succeed or fail at the same time;
- Transaction is very important in project development. It involves the consistency of data and cannot be careless;
- Ensure integrity and consistency
ACID principle of transaction:
- Atomicity:
- Transactions are atomic operations that either complete at the same time or have no effect at all.
- uniformity:
- Once all transaction actions are completed, the transaction will be committed, and the data and resources are in a consistent state that meets the business specifications
- The integrity of the data remains unchanged before and after the transaction is committed
- Isolation:
- Multiple transactions process the same data at the same time. Each transaction should be isolated from other transactions to prevent data corruption
- persistence
- Once the transaction is completed, no matter what errors occur in the system, the results will not be affected. Generally, once the transaction is committed, it will be persisted to the database.
Test:
Copy the above code into a new project
In the previous case, we added two methods to the userMapper interface, delete and add users;
//Add a user int addUser(User user); //Delete user by id int deleteUser(int id);
UserMapper file, we deliberately write deletes 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>
Write the UserMapperImpl implementation class of the interface. In the implementation class, we operate a wave
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper { //Add some operations public List<User> selectUser() { User user = new User(5, "Xiao Wang", "185161"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(5); return mapper.selectUser(); } //newly added public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } //delete public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); } }
test
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } }
Error reporting: sql exception. delete is written incorrectly
Result: the database result shows that the insertion is successful!
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;
13.2 transaction management in Spring
Spring defines an abstraction layer on top of different transaction management APIs. Yes, developers can use spring's transaction management mechanism without knowing 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 the operational business logic of each transaction
Declarative transaction management
- Generally, it is easier to use than programmed transaction management
- 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
1. Using spring management practice, 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">
2. JDBC transaction
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
3. After configuring the transaction manager, we need to configure the notification of transactions
<!--combination AOP Implement transaction weaving--> <!--Configure transaction notifications--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--Configure transactions for those methods--> <!--To configure the propagation properties of a transaction: new --> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
spring transaction propagation feature:
Transaction propagation behavior is how transactions propagate among multiple transaction methods when they call each other. spring supports 7 transaction propagation behaviors:
- propagation_requierd: if there is no current transaction, create a new transaction. If there is already a transaction, join the transaction;
- propagation_support: supports the current transaction. If there is no current transaction, it will be executed in a non transaction method
- propagation_mandatory: supports the current transaction. If there is no current transaction, an exception will be thrown
- propagation_requierd_new: the current transaction is not supported. Create a new transaction. If there is a current task, suspend the current task.
- propagation_not_supported: perform operations in a non transactional manner. If there is a transaction, suspend the current transaction.
- propagation_never: execute in a non transactional manner. If there is a transaction, an exception will be thrown
- propagation_nested: if there is a transaction, it will be executed within the nested transaction. If there is no transaction, it will be executed with propagation_required similar operations.
The default transaction propagation behavior of spring is; propagation_required, which is applicable to most situations.
For example, the methods we just mentioned have calls, so they will be placed in a group of transactions.
4. Configure AOP and import the header file of AOP
<!--Configure transaction entry--> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config>
5. Delete the data just inserted and test again
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } }
reflection:
Why transactions are needed?
- If transactions are not configured, there may be inconsistent data submission;
- If we do not configure declarative transactions in spring, we need to manually configure transactions in our code
- Transaction is very important in project development, which involves the consistency and integrity of data.