?? If it helps you??
?? Give a favor to the blogger??
?? Likes are the greatest encouragement to bloggers??
?? Love launch ~??
Crazy teacher B station course
Supporting code sorted by myself
Spring
- 1,Spring
- 2. Theoretical derivation of IOC
- 3,HelloSpring
- 4. How IOC creates objects
- 5. Spring configuration
- 6. Dependency injection
- 7. Automatic assembly of Bean
- 8. Development with annotations
- 9. Configure Spring using Java
- 10. Agent mode
- 11,AOP
- 12. Integration of Mybatis
- 13. Declarative transaction
- summary
1,Spring
1.1 INTRODUCTION
- Spring: Spring - > brings spring to the software industry!
- In 2002, the prototype of Spring framework was first launched: interface21 framework!
- The Spring framework is based on the interface21 framework. After redesigning and constantly enriching its connotation, the 1.0 official version was released on March 24, 2004.
- Rod Johnson, founder of spring framework, is a famous author. It's hard to imagine that rod Johnson's educational background really surprised many people. He is a doctor of Science in xieyuran, but his major is not computer, but music.
- spring: concept: make the existing technology easier to use, which is a hodgepodge in itself and integrates the existing technical framework!
SSH: Struct2+Spring+Hibernate!
SSM: SpringMvc + Spring + Mybatis!
Official website: Spring Framework Documentation
website: Index of /spring-framework/docs/4.3.9.RELEASE/spring-framework-reference
Official website download address: repo.spring.io
Github: spring-projects/spring-framework: Spring Framework (github.com)
Package Guide:
Maven Repository: org.springframework ? spring-webmvc (mvnrepository.com)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.16</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.16</version> </dependency>
1.2 advantages
- Spring is an open source and free framework (container)!
- Spring is a lightweight and non intrusive framework!
- Inversion of control (IOC), aspect oriented programming (AOP)!
- Support transaction processing and framework integration!
In a word, Spring is a lightweight framework of inversion of control (IOC) and aspect oriented programming (AOP)!
1.3 composition
Spring - seven core modules - Xiaobai Zhiqian - blog Park (cnblogs.com)
Core container (Spring Core)
The core container provides the basic functions of the spring framework. Spring organizes and manages various components and their relationships in Java applications in the form of beans. Spring uses BeanFactory to generate and manage beans, which is an implementation of the factory pattern. BeanFactory uses the inversion of control (IoC) pattern to separate the application's configuration and dependency specifications from the actual application code.
Application context (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, verification and scheduling functions.
Spring aspect oriented programming (Spring AOP)
Through the configuration management feature, the Spring AOP module directly integrates the aspect oriented programming function into the Spring framework. Therefore, it is easy to make any object managed by the Spring framework support 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 EJB components.
JDBC and DAO module (Spring DAO)
The abstract layer of JDBC and DAO provides a meaningful exception hierarchy, which 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 code that needs to be written, such as opening and closing links.
Object entity mapping (Spring ORM)
The Spring framework inserts several ORM frameworks to provide relational tools for ORM objects, including Hibernate, JDO, IBatis SQL Map, etc., all of which comply with Spring's common things and DAO exception hierarchy.
Web module (Spring Web)
The Web context module is built on the application context module and provides context for web-based applications. Therefore, the Spring framework supports integration with Struts, and the web module also simplifies the work of processing multi part requests and binding request parameters to domain objects.
MVC module (Spring Web MVC)
MVC framework is a full-featured MVC implementation for building Web applications. Through the policy interface, the MVC framework becomes highly configurable. MVC contains a large number of view technologies, including JSP, POI, etc. the model is composed of JavaBean s and stored in m. the view is a street corner, responsible for implementing the model, the controller represents the logic code, and c does the work. The functions of the Spring framework can be used in any J2EE server, and most of them are also applicable to an unmanaged environment. The core point of Spring is to support reusable business and data access objects that are not bound to specific J2EE services. There is no doubt that such objects can be reused between different J2EE environments, independent applications and test environments.
1.4 expansion
There is this introduction on Spring's official website: Modern ava development! To put it bluntly, it is Spring based development!
1.5. Common dependencies
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.16</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
SpringBoot
- A fast developing scaffold.
- A single microservice can be quickly developed based on SpringBoot.
- The agreement is greater than the configuration!
SpringCloud
- SpringCloud is implemented based on SpringBoots.
Because most companies are now using SpringBoot for rapid development, the prerequisite for learning SpringBoot is to fully master Spring and Spring MVC!
Disadvantages: after development for too long, it violates the original idea! Configuration is very cumbersome. People call it "configuration hell!"
2. Theoretical derivation of IOC
1.UserDao interface
2.UserDaolmpl implementation class
3.UserService business connection
4.UserServicelmpl business implementation class
Add configuration
Interface
UserDao.java
package com.blue.dao; public interface UserDao { void getUser(); }
UserDaoImpl.java
package com.blue.dao; public class UserDaoImpl implements UserDao{ @Override public void getUser() { System.out.println("Get user data by default"); } }
Business layer
UserService.java
package com.blue.service; public interface UserService { void getUser(); }
UserServiceImpl.java
package com.blue.service; import com.blue.dao.UserDao; import com.blue.dao.UserDaoImpl; public class UserServiceImpl implements UserService{ private UserDao userDao = new UserDaoImpl(); @Override public void getUser() { userDao.getUser(); } }
MyTest.java
package com.blue.dao; import com.blue.service.UserService; import com.blue.service.UserServiceImpl; public class MyTest { public static void main(String[] args) { ///Users actually call the business layer, and they don't need to touch the dao layer! UserService userService = new UserServiceImpl(); userService.getUser(); } }
To obtain data of other businesses, please refer to the following:
UserDaoMysqlImpl.java
package com.blue.dao; public class UserDaoMysqlImpl implements UserDao{ @Override public void getUser() { System.out.println("Mysql Get user data"); } }
The following changes are required:
This moves the source code. If the code is long, it will be complicated
In our previous business, the user's needs may affect our original code, and we need to modify the original code according to the user's needs!
We use a Set interface to implement. Revolutionary changes have taken place!
- Before, the program was actively creating objects! Control is in the hands of the program ape!
- After using set injection, the program no longer has initiative, but becomes a passive receiver!
UserServiceImpl.java
package com.blue.service; import com.blue.dao.UserDao; import com.blue.dao.UserDaoImpl; import com.blue.dao.UserDaoMysqlImpl; public class UserServiceImpl implements UserService{ private UserDao userDao; //Using set to dynamically implement value injection public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); } }
MyTest.java
package com.blue.dao; import com.blue.service.UserService; import com.blue.service.UserServiceImpl; public class MyTest { public static void main(String[] args) { ///Users actually call the business layer, and they don't need to touch the dao layer! UserServiceImpl userService = new UserServiceImpl(); userService.setUserDao(new UserDaoMysqlImpl()); userService.getUser(); } }
This idea essentially solves the problem. We program apes no longer need to manage the creation of objects. The coupling of the system is greatly reduced, and we can focus more on the implementation of the business! This is the prototype of IOC!
2.1 IOC intrinsic control inversion
**IoC(Inversion of Control) is a design idea. DI (dependency injection) is a way to implement Ioc. * * some people think that DI is just another way of saying oC. In the program without oC, we use object-oriented programming. The creation of objects and the dependencies between objects are completely hard coded in the program. The creation of objects is controlled by the program itself. After inversion of control, the creation of objects is transferred to a third party. Personally, I think the so-called inversion of control is that the way to obtain dependent objects is reversed.
When configuring a Bean in XML, the definition information of the Bean is separated from the implementation, and the annotation method can integrate the two. The definition information of the Bean is directly defined in the implementation class in the form of annotation, thus achieving the goal of zero configuration.
Inversion of control is a way to produce or obtain specific objects through description (XML or annotation) and through a third party. The IoC container implements inversion of control in Spring, and its implementation method is dependency injection (DL).
3,HelloSpring
Test 1
New module
beans.xml
MyTest.java
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
result:
Test 2
Create a new beans.xml
[the external link image transfer failed. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ppvkurb6-1648559381967) (C: usersdlmuappdataroaming typora ypora user images-20220329121647162. PNG)]
<?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.blue.dao.UserDaoMysqlImpl"/> <bean id="oracleImpl" class="com.blue.dao.UserDaoOracleImpl"/> <bean id="UserServiceImpl" class="com.blue.service.UserServiceImpl"> <property name="userDao" ref="mysqlImpl"/> </bean> <!-- ref:lead Spring Created object in container value: Specific value, basic data type,! --> </beans>
package com.blue.dao; import com.blue.service.UserServiceImpl; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl"); userServiceImpl.getUser(); } }
result
Call here
4. How IOC creates objects
The core of IOC is factory mode, and the core of AOP is agent mode
1. Create an object using parameterless construction. Default!
package com.blue.pojo; public class User { private String name; public User() { System.out.println("User Parameterless construction of!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); } }
<?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.blue.pojo.User"> <property name="name" value="blue"/> </bean> </beans>
import com.blue.pojo.User; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); user.show(); } }
2. Suppose we want to create an object using a parameterized construct.
package com.blue.pojo; public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); } }
1. Subscript assignment
<?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.blue.pojo.User"> <constructor-arg index="0" value="blueJava"/> </bean> </beans>
import com.blue.pojo.User; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); user.show(); } }
2. Type
<bean id="user" class="com.blue.pojo.User"> <constructor-arg type="java.lang.String" value="blue"/> </bean>
3. Parameter name
<bean id="user" class="com.blue.pojo.User"> <constructor-arg name="name" value="blue"/> </bean>
Summary: when the configuration file is loaded, the objects managed in the container have been initialized!
5. Spring configuration
5.1 alias
5.2. Bean configuration
ID: unique identifier of the bean, which is equivalent to the object name we learned
cLass: full qualified name corresponding to bean object: package name + cLass
Name: also an alias, and name can take multiple aliases at the same time
UserT.java
package com.blue.pojo; public class UserT { private String name; public UserT() { System.out.println("UserT Parameterless construction of!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+name); } }
beans.xml
<bean id="userT" class="com.blue.pojo.UserT" name="user2"> </bean>
test
import com.blue.pojo.UserT; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserT user = (UserT) context.getBean("user2"); user.show(); } }
result
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 multiple people developing in the project, and these three people copy different class development. Different classes need to be registered in different beans. We can use import to merge all the beans.xml into one general
- Zhang San
- Li Si
- Wang Wu
- applicationContext.xml
When using, just use the general configuration directly
<?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"> <import resource="beans.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/> </beans>
test
import com.blue.pojo.UserT; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserT user = (UserT) context.getBean("u2"); user.show(); } }
6. Dependency injection
6.1. Constructor injection
As already mentioned
6.2. Set mode injection [ key ]
Dependency injection: Set injection!
- Dependency: the creation of bean objects depends on containers!
- Injection: all the attributes in the bean object are injected by the container!
[environment construction]
- Complex type
package com.blue.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
- Real test object
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 into;
- 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="student" class="com.blue.pojo.Student"> <!-- First, ordinary injection,value --> <property name="name" value="blue"/> </bean> </beans>
-
MyTest
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());
}
}
result:
Other methods
address+
result:
6.3. Expansion mode: injection
We can use the P command space and the C command space for injection
Official explanation:
Note: p naming and c namespace cannot be used directly, and xml constraints need to be imported!
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
Label:
xmlns:p="http://www.springframework.org/schema/p"
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.blue.pojo.User" p:name="blue" p:age="18"/> </beans>
Add configuration
test:
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml"); User user = context.getBean("user", User.class); System.out.println(user); } }
result:
Label:
xmlns:c="http://www.springframework.org/schema/c"
public class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; }
<bean id="user" class="com.blue.pojo.User" p:name="blue" p:age="18"/> <bean id="user" class="com.blue.pojo.User" c:age="18" c:name="blue"/>
6.4. Scope of bean
1. Focus of singleton mode (Spring default mechanism)
For single line
2. Prototype mode:
For multithreading
Every time you get from the container, a new object will be generated!
3. Others
The other request s, session s, application s can only be used in web development!
7. Automatic assembly of Bean
- Automatic assembly is a way for Spring to meet bean dependency!
- Spring will automatically find in the context and automatically assemble properties for the bean!
There are three assembly methods in Spring:
- Configuration displayed in xml
- Display configuration in java
- Implicit automatic assembly bean [important]
7.1 test
1. Environment construction: one person has two pets!!
cat
public class Cat { public void shout(){ System.out.println("miao~"); } }
dog
people
public class People { private Cat cat; private Dog dog; private String name; }
beans
<?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="cat" class="com.blue.pojo.Cat"/> <bean id="dog" class="com.blue.pojo.Dog"/> <bean id="people" class="com.blue.pojo.People"> <property name="name" value="blue"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean> </beans>
public class MyTest { @Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = context.getBean("people", People.class); people.getCat().shout(); people.getDog().shout(); } }
7.2. ByName automatic assembly
byName: match the attribute name and id,
byType: match globally unique according to the type and class of the attribute
7.3. ByType automatic assembly
Summary:
- When byname is used, it is necessary to ensure that the IDs of all beans are unique, and this bean needs to be consistent with the value of the set method of the automatically injected attribute!
- When byType is used, it is necessary to ensure that the class of all beans is unique, and the bean needs to be consistent with the type of the automatically injected attribute!
7.4. Use notes to realize automatic assembly
jdk1.5 supports annotations, and spring 2.5 supports annotations!
The introduction of annotation-based configuration raised the question of whether this approach is "better"than XML.
Notes to use:
1. Import constraint context constraint
2. Support for configuring annotations: < context: annotation config / >
<?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"> <context:annotation-config/> </beans>
@Autowired
Use it directly on the content! It can also be used in the set mode!
Using Autowired, we don't need to write the Set method, provided that your auto assembled property exists in the IOC (Spring) container and conforms to the name byname!
@Autowired will inject according to the type first. If there are multiple instances meeting the type in the container, it will inject according to the ID. Injection is not just based on type
public class People { @Autowired private Cat cat; @Autowired private Dog dog; private String name; }
If the environment of @ Autowired auto assembly is relatively complex, and auto assembly cannot be completed through an annotation @ Autowired, we can use @ Qualifier(value = "XXX") to configure the use of @ Autowired and specify a unique bean object injection!
@Nullable
polular science:
@Nullable The field is marked with this annotation, which means that this field can be nu11;
Source code:
public @interface Autowired { boolean required() default true; }
public class People { @Autowired @Qualifier(value = "cat22") private Cat cat; @Autowired private Dog dog; private String name; }
@Resource
Summary
@Difference between Resource and @ Autowired
- They are used for automatic assembly and can be placed on the attribute field
- @Autowired is implemented by byType, and this object must have [common]
- @Resource is implemented by byname by default. If the name cannot be found, it is implemented by byType! If neither of them can be found, an error will be reported! [common]
- Difference: Autowired is implemented by byType; Resource is implemented by byname by default
8. Development with annotations
After spring 4, if you want to develop with annotations, you must ensure that the package of aaop is imported
To use annotations, you need to import context constraints and add 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" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/conaoptext/spring-aop.xsd"> <!-- Enable annotation support--> <context:annotation-config/> </beans>
modular
1.bean
applicationContext
2. How to inject attributes
user
@Component public class User { public String name = "blue"; }
@Component
Component, placed on the class, indicates that this class is managed by Spring, that is, bean!
test
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = context.getBean("user", User.class); System.out.println(user.name); } }
Remove the name content, and the test result is null
@Value
3. Derived notes
@Component has several derived annotations. In our web development, we will layer according to the mvc three-tier architecture
- dao [@Repository]
- service [Service]
- controller [@Controller]
These four annotation functions are the same. They all represent registering a class in Spring and assembling beans
4. Automatic assembly configuration
@Autowired: Automatic assembly through type. name If Autowired If the attribute on the automatic assembly cannot be unique, you need to pass the@Qualifier(va1ue="xxx") @Nullable : The field is marked with this annotation, which means that this field can be null; @Resource : Automatic assembly by name. Type.
When a Class A needs a variable of type B, add this annotation when declaring the variable, and spring will look for it in the container
5. Scope
@Component @Scope("prototype") public class User { public String name; @Value("blue2") public void setName(String name) { this.name = name; } }
6. Summary
xml and annotation:
- xml is more versatile and suitable for any occasion! Simple and convenient maintenance
- Annotations are not used by your own class, and maintenance is relatively complex!
xml and annotation best practices:
-
xml is used to manage bean s;
-
Annotations are only responsible for the injection of attributes;
-
In the process of using, we only need to pay attention to one problem: to make annotations effective, we need to turn on annotation support
<context:component-scan base-package="com.blue"/> <context:annotation-config/>
9. Configure Spring using Java
Now we will not use Spring's xml configuration at all, and leave it to Java!
JavaConfig is a sub project of Spring. After Spring 4, it has become a core function!
be careful:
- If package scanning is enabled, after loading the configuration class, you can get the objects in the configuration class through reflection,
- @Bean s can be used to obtain objects such as database Connection pools (connections) through methods
- @Bean only writes on the method and returns an object, but generally does not get the object already in the container
@Component public class User { private String name; public String getName() { return name; } @Value("blue111") public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + ''' + '}'; } }
@Configuration @ComponentScan("com.blue.pojo") public class BlueConfig { @Bean public User getUser(){ return new User(); } }
method
When you use @ configuration to declare a configuration class, there are two ways to generate a Bean
- Define a method in the configuration class and declare it with @ Bean annotation
- Annotate the user class with @ Component, and configure the class with @ ComponentScan("path of the user class"), which will automatically scan. The id used in getBean is the lower case class name (user)
- If both methods are used, two objects will be created. The object created by @ Component is obtained by getBean("user"), and the object declared by @ Bean in the configuration class is obtained by getBean("getUser"). These two objects are different
This pure Java configuration can be seen everywhere in SpringBoot!
10. Agent mode
Why learn agent mode?
Because this is the bottom of spring AOP! [SpringAOP and SpringMVC]
Classification of proxy mode:
- Static proxy
- Dynamic proxy
10.1. Static agent
Role analysis:
- Abstract role: it is usually solved by using interfaces or abstract classes
- Real role: the role of the agent
- Proxy role: acting as a real role. After acting as a real role, we usually do some ancillary operations
- Customer: the person who accesses the proxy object!
Code steps:
1. Interface - Rent
2. Real role Host
3. Proxy role - proxy
4. Client access agent role - client
1. Test - no mediation
Abstract role
Real character
customer
2. Intermediary
Summary
Benefits of proxy mode:
- It can make the operation of real characters more pure! Don't pay attention to some public business
- The public will be handed over to the agent role! The division of business has been realized!
- When public business is expanded, it is convenient for centralized management!
Disadvantages:
- A real role will generate a proxy role; The amount of code will double, and the development efficiency will become low
10.2 deepen understanding
Code: corresponding to 08-dmeo02;
Talk about AOP
UserService
public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
UserServiceImpl -- real object
//Real object public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("Added a user"); } @Override public void delete() { System.out.println("Deleted a user"); } @Override public void update() { System.out.println("Modified a user"); } @Override public void query() { System.out.println("Queried a user"); } }
UserServiceProxy -- proxy
public class UserServiceProxy implements UserService{ private UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } @Override public void add() { log("add"); userService.add(); } @Override public void delete() { log("delete"); userService.delete(); } @Override public void update() { log("update"); userService.update(); } @Override public void query() { log("query"); userService.query(); } //Log method public void log(String msg){ System.out.println("Used"+msg+"method"); } }
Bold style Client
public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); proxy.setUserService(userService); proxy.add(); } }
result:
10.3 dynamic agent
Dynamic proxy has the same role as static proxy
The proxy class of dynamic proxy is dynamically generated, not written directly by us!
Dynamic agents are divided into two categories: interface based dynamic agents and class based dynamic agents
- Interface based JDK dynamic proxy [we use it here]
- Based on: cglib
- java bytecode implementation: javasist
Two classes need to be understood:
- Proxy: proxy,
- InvocationHandler: call handler, which is the interface implemented by the call handler of the proxy instance.
ProxyInvocationHandler
Client
public class Client { public static void main(String[] args) { //Real character Host host = new Host(); //Proxy role: no ProxyInvocationHandler pih = new ProxyInvocationHandler(); //Handle the interface object we want to call through the caller processing role pih.setRent(host); Rent proxy = (Rent) pih.getProxy(); proxy.rent(); } }
demo04 - real dynamic
public class ProxyInvocationHandler implements InvocationHandler { //Proxied interface private Object target; public void setTarget(Object target) { this.target = target; } //Generate the obtained proxy class public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } //Process the proxy instance and return the result @Override 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("Executed"+msg+"method"); } } package com.blue.demo04; import com.blue.demo02.UserService; import com.blue.demo02.UserServiceImpl; public class Client { public static void main(String[] args) { //Real character UserServiceImpl userService = new UserServiceImpl(); //Proxy role: no ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(userService); //Handle the interface object we want to call through the caller processing role UserService proxy = (UserService) pih.getProxy(); proxy.delete(); } }
Benefits of dynamic proxy:
- It can make the operation of real characters more pure! Don't pay attention to it
- The public business is public, so it is given to the agent role! The division of business has been realized!
- When public business is expanded, it is convenient for centralized management!
- A dynamic proxy class represents an interface, which is generally a corresponding class of business
- A dynamic proxy class can proxy multiple classes as long as it implements the same interface
11,AOP
11.1 what is AOP
AOP(Aspect Oriented Programming) means: aspect oriented programming, a technology that realizes the unified maintenance of program functions through precompiling and dynamic agents at runtime. AOP is the continuation of OOP, a hot spot in software development, an important content of the sting framework, and a derivative paradigm of functional programming. AOP can be used to isolate various parts of business logic, thus reducing the coupling between various parts of business logic, improving the reusability of programs, and improving the efficiency of development.
11.2. The role of Aop in Spring
Provide declarative transactions; Allow users to customize facets
- Crosscutting concerns: methods or functions that span multiple modules of an application. That is, the part that has nothing to do with our business logic, but we need to pay attention to is the crosscutting concern. 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 completed. That is, it is a method in a class.
- Target: the notified object.
- Proxy (Poy): an object created after notification is applied to the target object.
- Pointcut: the definition of the "place" where the facet notification is executed. Jointpoint: the execution point matching the pointcut.
In spring AOP, crosscutting logic is defined through Advice. Spring supports five types of Advice:
11.3. Using Spring to implement Aop
[key] to use AOP weaving, you need to import a dependent package!
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> </dependencies>
modular
service
public interface UserService { public void add(); public void delete(); public void update(); public void select(); } public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("Added a user"); } @Override public void delete() { System.out.println("Deleted a user"); } @Override public void update() { System.out.println("Updated a user"); } @Override public void select() { System.out.println("Queried a user"); } }
Method 1 - use native Spring API interface [mainly implemented by Spring API interface]
Spring configuration -- applicationContext.xml
test
import com.blue.service.UserService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //Dynamic proxy: the proxy is an interface UserService userService = context.getBean("userService", UserService.class); userService.add(); } }
Method 2 - user defined class [mainly defined by section]
public class DiyPointCut { public void before(){ System.out.println("=============Before method execution==========="); } public void after(){ System.out.println("=============After method execution==========="); } } <!-- Method 2: custom class --> <bean id="diy" class="com.blue.diy.DiyPointCut"/> <aop:config> <!-- Custom cut plane, ref Class to be used --> <aop:aspect ref="diy"> <aop:pointcut id="point" expression="execution(* com.blue.service.UserServiceImpl.*(..))"/> <!-- notice --> <aop:before method="before" pointcut-ref="point"/> <aop:before method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
result:
Method 3: implement AOP with annotation
<!-- Mode 3--> <bean id="annotationPointOut" class="com.blue.diy.AnnotationPointCut"/> <!--Enable annotation support--> <aop:aspectj-autoproxy/>
AnnotationPointCut
package com.blue.diy; 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.blue.service.UserServiceImpl.*(..))") public void before(){ System.out.println("=============Before method execution==========="); } @After("execution(* com.blue.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=============After method execution==========="); } }
Extension:
12. Integration of Mybatis
Steps:
- Import relevant jar packages
- junit
- mybatis
- mysql database
- spring related
- aop weaving
- mybatis-.spring[new]
junit
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.16</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.16</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.14</version> </dependency> <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.20</version> </dependency> </dependencies> <!--stay build Medium configuration resources,To prevent the failure of our resource export--> <build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>**/*.properties</exclude> <exclude>**/*.xml</exclude> </excludes> <filtering>false</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
- Write configuration file
- test
12.1. Recall mybatis
1. Write entity class
package com.blue.pojo; import lombok.Data; @Data public class User { private int id; private String name; private String pwd; }
2. Prepare core configuration file
<?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.blue.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.blue.mapper.UserMapper"/> </mappers> </configuration>
3. Compile interface
package com.blue.mapper; import com.blue.pojo.User; import java.util.List; public interface UserMapper { public List<User> selectUser(); }
4. Write Mapper.Xml
<?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.blue.dao.UserMapper"> <select id="selectUser" resultType="com.blue.pojo.User"> select * from mybatis.user </select> </mapper>
5. Test
import com.blue.mapper.UserMapper; import com.blue.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; import static java.lang.System.in; public class MyTest { @Test public void test() throws IOException { String resources = "mybatis-config.xml"; InputStream in = Resources.getResourceAsStream(resources); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = sqlSessionFactory.openSession(true); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.selectUser(); for (User user : userList) { System.out.println(user); } sqlSession.close(); } }
result:
12.2,Mybatis-spring
First method
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" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/conaoptext/spring-aop.xsd"> <!-- DataSource:use Spring Data source for Mybatis Configuration of c3p0 dbcp druid Here we make Spring Provided JDBC:org.springframework.jdbc.datasource --> <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?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!-- sqLSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- binding Mybatis configuration file --> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath*:com/blue/mapper/*.xml"/> </bean> <!-- SqLSessionTempLate:Wei: it's me M We use sqLSession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <bean id="userMapper" class="com.blue.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> </beans>
UserMapperImpl
public class UserMapperImpl implements UserMapper{ // All our operations are performed using sqlSession. In the past, we now use SqlSessionTemplate; private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } @Override public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } }
MyTest
public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring_dao.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
result:
The second method
UserMapperImpl2
package com.blue.mapper; import com.blue.pojo.User; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{ @Override public List<User> selectUser() { return getSqlSession().getMapper(UserMapper.class).selectUser(); } }
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" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/conaoptext/spring-aop.xsd"> <import resource="spring_dao.xml"/> <bean id="userMapper" class="com.blue.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> <bean id="userMapper2" class="com.blue.mapper.UserMapperImpl2"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans> public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper2", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
result:
Sequence:
13. Declarative transaction
13.1 review affairs
- Treat a group of businesses as one business; Either they succeed or they fail!
- Transactions are very important in project development. They involve data consistency. We can't be sloppy!
- Ensure integrity and consistency;
Transaction ACID principle:
- Atomicity
- uniformity
- Isolation: multiple businesses may operate on the same resource to prevent data corruption
- Persistence: once a transaction is committed, no matter what happens to the system, the result will not be affected and will be written to the memory persistently!
spring-11-transaction
Stick
User,UserMapper,UserMapper.xml,UserMapperImpl,mybatis-config.xml,spring_dao.xml,applicationContext.xml
UserMapperImpl
package com.blue.mapper; import com.blue.pojo.User; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{ // All our operations are performed using sqlSession. In the past, we now use SqlSessionTemplate; @Override public List<User> selectUser() { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.selectUser(); } }
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" xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/conaoptext/spring-aop.xsd"> <import resource="spring_dao.xml"/> <bean id="userMapper" class="com.blue.mapper.UserMapperImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
Mytest
public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
result:
UserMapper interface
public interface UserMapper { public List<User> selectUser(); //Add a user public int addUser(User user); // Delete a user public int deleteUser(int id); }
User - subject
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; }
UserMapperImpl -- implementation method
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{ // All our operations are performed using sqlSession. In the past, we now use SqlSessionTemplate; @Override public List<User> selectUser() { User user = new User(5, "blue", "121334"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(5); return mapper.selectUser(); } @Override public int addUser(User user) { return getSqlSession().getMapper(UserMapper.class).addUser(user); } @Override public int deleteUser(int id) { return getSqlSession().getMapper(UserMapper.class).deleteUser(id); } }
UserMapper.xml - configuration
<?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"> <!--configuration Core profile--> <mapper namespace="com.blue.mapper.UserMapper"> <select id="selectUser" resultType="user"> select * from mybatis.user; </select> <insert id="addUser" parameterType="user"> insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd}); </insert> <delete id="deleteUser" parameterType="int"> delete from mybatis.user where id=#{id} </delete> </mapper>
Mytest
public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
result:
13.2. Transaction management in spring
- Declarative transactions: AOP
- Programming transaction: it is necessary to manage the transaction in the code
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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- DataSource:use Spring Data source for Mybatis Configuration of c3p0 dbcp druid Here we make Spring Provided JDBC:org.springframework.jdbc.datasource --> <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?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <!-- sqLSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- binding Mybatis configuration file --> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath*:com/blue/mapper/*.xml"/> </bean> <!-- SqLSessionTempLate:Wei: it's me M We use sqLSession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!-- <bean id="userMapper" class="com.blue.mapper.UserMapperImpl">--> <!-- <property name="sqlSession" ref="sqlSession"/>--> <!-- </bean>--> <!-- Configure claim transactions --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- combination AOP Realize transaction weaving --> <!-- Configure transaction notification --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <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> <!-- Configure transaction entry --> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.blue.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> </beans>
Mytest
public class Mytest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList = userMapper.selectUser(); for (User user : userList) { System.out.println(user); } } }
Thinking: why do I need affairs?
- If the transaction is not configured, the data submission may be inconsistent;
- If we do not configure declarative transactions in SPRING, we need to manually configure transactions in the code!
- Transactions are very important in the development of the project. The consistency and integrity of data in the design should not be sloppy!
summary
It is important to master, and it is best to write in java
Dynamic proxy: Reflection
last
I know that most junior and middle-level Java engineers want to improve their skills, often by groping for growth or signing up for classes, but for training institutions, the tuition fee is nearly 10000 yuan, which is really a lot of pressure. The self-study effect that is not systematic is inefficient and long, and it is easy to encounter the stagnation of ceiling technology!
Therefore, I have collected and sorted out a complete set of learning materials for Java development and sent it to you. The original intention is also very simple, that is, I hope to help friends who want to improve themselves by self-study but do not know where to start, and at the same time reduce everyone's burden.
Xiaobian has been encrypted: ahr0chm6ly9kb2nzlnfxlmnvbs9kb2mvrvrvm9asgxqzuvstlkwunc = = for security reasons, we have encoded the website through base64. You can get the website through base64 decoding.