Spring learning notes

Posted by bhagwat on Tue, 01 Feb 2022 19:06:02 +0100


advantage:

  • Spring is an open source, free framework (container)
  • Spring is a lightweight, non intrusive framework
  • Inversion of control (IOC), aspect oriented programming (AOP)
  • Support transaction, support for framework integration

jar packages to import:

<!-- Importing this package will directly import other packages, including core,context,aop,bean... My bag-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.5</version>
</dependency>

1, IOC control reversal

That is to leave the operation of creating objects to spring, which can decouple and increase the scalability of the program.

If IOC is not used, the creation object is created as follows:

1. Traditional object creation method:

DAO layer:

public interface UserDao {
    void getUsers();
}

public class UserDaoImpl implements UserDao {
    public void getUsers() {
        System.out.println("Get user list!");
    }
}

public class UserDaoMysqlImpl implements UserDao{
    public void getUsers() {
        System.out.println("obtain mysql User list!");
    }
}

public class UserDaoOracleImpl implements UserDao{
    public void getUsers() {
        System.out.println("obtain oracle User list!");
    }
}

service layer:

public interface UserService {
    void getUsers();
}

public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();
    
    public void getUsers() {
        userDao.getUsers();
    }
}

Test class:

public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    userService.getUsers();
}

In this case, the method of UserDaoImpl implementation class is called. If you want to call the method of UserDaoMysqlImpl or UserDaoOracleImpl, you need to modify the code in the service layer and change private UserDao userDao = new UserDaoImpl() to private UserDao userDao = new UserDaoMysqlImpl(), resulting in great coupling between various modules, Moreover, if you modify the requirements later, you have to modify the source code. The flexibility is very poor, so you need to reverse the control of spring and create objects through the configuration file. In this way, the initiative is in the hands of users, not programmers

2. IOC creation object:

2.1 creation of nonparametric structure:

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="studentDaoImpl" class="com.nari.dao.StudentDaoImpl"/>
    <bean id="teacherDaoImpl" class="com.nari.dao.TeacherDaoImpl"/>

    <bean id="studentServiceImpl" class="com.nari.service.StudentServiceImpl">
        <property name="studentDao" ref="studentDaoImpl"/>
    </bean>

</beans>

DAO layer:

public interface StudentDao {
    void getStudent();
}

public class StudentDaoImpl implements StudentDao{
    @Override
    public void getStudent() {
        System.out.println("Get students!");
    }
}

public class TeacherDaoImpl implements StudentDao{
    @Override
    public void getStudent() {
        System.out.println("Get teacher!");
    }
}

Service layer:

public interface StudentService {
    void getStudent();
}

public class StudentServiceImpl implements StudentService{
    @Setter
    private StudentDao studentDao;
    @Override
    public void getStudent() {
        studentDao.getStudent();
    }
}

Test class:

@Test
public void getUser(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    StudentServiceImpl studentServiceImpl = (StudentServiceImpl) applicationContext.getBean("studentServiceImpl");
    studentServiceImpl.getStudent();
}

In this way, the object is created through the configuration file. As soon as the program runs, spring will automatically help us create the object

2.2 parametric structure creation:
<!-- There are three ways to create objects with parametric construction -->
<!-- How to use Subscripts -->
<constructor-arg index="0" ref="studentDaoImpl"/>
<!-- Use attribute name -->
<constructor-arg name="studentDao" ref="studentDaoImpl"/>
<!-- Use attribute type -->
<constructor-arg type="com.nari.dao.StudentDao" ref="studentDaoImpl"/>

It is recommended to use attribute names for creation

2, spring configuration file details:

Alias: alias (not a fully qualified name for a class, but an id)

<?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="studentDaoImpl" class="com.nari.dao.StudentDaoImpl"/>

    <bean id="studentServiceImpl" class="com.nari.service.StudentServiceImpl">
        <property name="studentDao" ref="studentDaoImpl"/>
    </bean>
    
	<alias name="studentDaoImpl" alias="student"/>
</beans>

Import: import configuration file

It is mainly used for multi person collaboration. For example, there is a main configuration file applicationContent XML, a number of different developer configuration files, beans XML, you can import the slave configuration file in the master configuration file

<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

Spring will automatically integrate the configuration files. If there is the same configuration, spring will automatically select one of them

bean objects: Creating

<bean id="studentDaoImpl" class="com.nari.dao.StudentDaoImpl" name="u1 u2,u3;u4"/>

The name attribute is also an alias, which is much more powerful than the alias tag. It is recommended to use it. It can have multiple aliases and can handle any separators you can think of

3, Dependency injection

This is the way to create objects. The essence is set injection. If there is no set method, injection cannot be carried out

Dependency injection:

  • Dependency: the creation of bean objects depends on the spring container
  • Injection: all attributes in the bean object are injected by the container

At present, there are three injection methods:

3.1 constructor injection

Parametric structural injection

Nonparametric structural injection

3.2 other injection methods

p namespace injection: p is property injection

<bean id="address" class="com.nari.pojo.Address" p:address="Shanxi"/>

c namespace injection: c is the constructor constructor injection

<bean id="address" class="com.nari.pojo.Address" c:address="Yuncheng"/>

Note:

  • Relevant constraints need to be imported before use

  • xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    
3.3 set injection (important)

pojo entity class:

@Data
public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String, String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="address" class="com.nari.pojo.Address">
        <property name="address" value="Shanxi"/>
    </bean>

    <bean id="student" class="com.nari.pojo.Student">
        <!-- 1. Basic type injection -->
        <property name="name" value="Zhang San"/>

        <!-- 2. Reference type injection -->
        <property name="address" ref="address"/>

        <!-- 3. Array injection -->
        <property name="books">
            <array>
                <value>language</value>
                <value>mathematics</value>
                <value>Politics</value>
                <value>English</value>
            </array>
        </property>

        <!-- 4. list Set injection -->
        <property name="hobbys">
            <list>
                <value>read a book</value>
                <value>study</value>
                <value>fall in love</value>
            </list>
        </property>

        <!-- 5. map Type injection -->
        <property name="card">
            <map key-type="java.lang.String" value-type="java.lang.String">
                <entry key="ID" value="14273100114580"/>
                <entry key="Student ID card" value="20210678"/>
                <entry key="bank card" value="12345812354531351352"/>
            </map>
        </property>
        <!-- 6. set Type injection -->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>BOB</value>
                <value>COC</value>
            </set>
        </property>
        
        <!-- 7. NULL Type injection -->
        <property name="wife">
            <null/>
        </property>

        <!-- 8. properties Type injection -->
        <property name="info">
            <props>
                <prop key="url">java.lang.String</prop>
                <prop key="driver">jdbc://localhost:5236/DAMENG</prop>
                <prop key="username">root</prop>
                <prop key="password">ruirui</prop>
            </props>
        </property>
    </bean>
</beans>

4, Scope of Bean

[the external chain image transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-plk2i8ea-1622863598370) (/ home / Yijie /. Config / typora / typora user images / image-20210418231354846. PNG)]

The scope attribute in the bean tag is mainly divided into four values:

  • singleton: singleton mode (global sharing)
  • Prototype: prototype pattern (non global sharing)
  • request
  • session

Note:

  • In singleton mode, the hashcode of two created objects is the same, which is used in single thread
  • In the prototype mode, the two created objects are different and are used when multithreading

5, Auto assemble 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

In spring, there are three assembly methods:

  • Explicit configuration in xml: the above injection
  • Explicit assembly in java code
  • Implicit automatic assembly bean "important"

Assembly method 1: 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="cat" class="com.nari.spring.pojo.Cat"/>
    <bean id="dog" class="com.nari.spring.pojo.Dog"/>

    <bean id="person" class="com.nari.spring.pojo.Person" autowire="byName">
        <property name="name" value="Zhang San"/>
    </bean>
</beans>

Through the autowire attribute of the bean tag, this attribute has five values:

1. byName: match by the id of the bean tag

2. byType: match through the class attribute of the bean tag

3. Constructor: match by constructor

4. Default: matches by default. The default method is no

5. No: no automatic assembly

Note:

  • The byName method must ensure the unique id of the bean, and the id cannot be omitted
  • The byType method must ensure that the class of the bean is unique, and the id can be omitted

Assembly mode 2: Notes

1,@Autowired
public class Person {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String 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"
       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/>

    <bean id="cat" class="com.nari.spring.pojo.Cat"/>
    <bean id="dog" class="com.nari.spring.pojo.Dog"/>
    <bean id="person" class="com.nari.spring.pojo.Person"/>
</beans>
public class SpringTest {
    @Test
    public void DemoTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = applicationContext.getBean("person",Person.class);
        person.getDog().shout();
        person.getCat().shout();
    }
}

matters needing attention:

  • Need to import related constraints: import context constraints

  • Annotation support needs to be enabled

  • @The Autowired annotation has one and only one attribute, required

    public @interface Autowired {
        boolean required() default true;
    }
    

    If required is set to false, the object can be null

    public class Person {
        @Autowired(required = false)
        private Cat cat;
    }
    
  • @The Autowired annotation can be placed on the set method, and the effect is the same as that on the attribute

    @Autowired
    public void setCat(Cat cat) {
        this.cat = cat;
    }
    
  • If the @ Autowired annotation is used, the set method can be omitted, but the get method cannot be omitted

  • @Autowired realizes automatic assembly through byName by default. If the name does not match, it will match through byType

2,@Qualifier

If the automatic assembly environment of @ Autowired is complex and there are multiple beans with the same type and different IDS, you can use @ Qualifier annotation to specify a bean to assemble

<context:annotation-config/>
<bean id="cat111" class="com.nari.spring.pojo.Cat"/>
<bean id="cat11" class="com.nari.spring.pojo.Cat"/>

<bean id="dog111" class="com.nari.spring.pojo.Dog"/>
<bean id="dog11" class="com.nari.spring.pojo.Dog"/>
public class Person {
    @Autowired
    @Qualifier(value = "cat11")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog111")
    private Dog dog;
}
3,@Resource

This annotation comes with java and does not belong to spring, but its function is the same as @ Autowired. It is also used to realize automatic assembly. It is equivalent to the collection of @ Autowired and @ Qualifier

public class Person {
    @Autowired
    @Qualifier(value = "cat11")
    private Cat cat;
    
    @Resource(name = "dog111")
    private Dog dog;
}

This annotation is also matched through the attribute name first. If it cannot be matched, it is matched through the type

4,@Nullable

The annotation is placed on the attribute, indicating that the attribute can be null

public Person(@Nullable String name) {
    this.name = name;
}

6, Using annotation development

After spring 4, to develop with annotations, you need to import aop packages first

Secondly, import context constraints and enable annotation support and annotation scanning

<?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 scanning -->
    <context:component-scan base-package="com.nari"/>
    <context:annotation-config/>
</beans>

bean injection

amount to:

<bean id="user" class="com.nari.pojo.User">
@Component
public class User {
    public String name;
}

Attribute injection

amount to:

<property name="name" value="Zhang San"/>
@Component
public class User {
    @Value(value = "Zhang San")
    public String name;
}

be careful:

  • The injected attribute must be public, otherwise the attribute cannot be obtained
  • Using annotations, you can omit the get and set methods of attributes. If xml configuration is used, there must be a set method
  • If the bean name is not specified, the default class name is lowercase. You can also customize the bean name

@Derived annotation of Component

@Repository,@Service,@Controller

Corresponding to dao layer, service layer and controller layer respectively, the effect is equivalent to @ Component, which means

Scope

@Component("user")
@Scope(value = "singleton")
public class User {
    @Value(value = "Zhang San")
    public String name;
}

The difference between xml and annotation

  • xml is more versatile, applicable to various scenarios and easy to maintain
  • Annotations are not their own classes. They cannot be used and are complex to maintain
  • The best way is: xml is used to manage bean s and annotations are used for attribute injection

7, java based alternative xml configuration: AppConfig

Completely abandon xml configuration and use java code instead of creating xml configuration file

1. Create java configuration class

@Configuration
@ComponentScan(value = "com.nari.pojo")
public class UserConfig {
    @Bean
    public User getUser(){
        return new User();
    }
}
  • @Configuration indicates that this class is a java configuration class
  • @ComponentScan scans the annotation of which package or class
  • Create a new method of pojo's return value type

2. Create pojo class

@Data
@Component
public class User {
    @Value(value = "123123")
    private String name;
}

3. Test

public class UserTest {
    @Test
    public void UserDemoTest(){
        ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
        User getUser = context.getBean("getUser", User.class);
        System.out.println(getUser.getName());
    }
}
  • The AnnotationConfigApplicationContext object needs to be created, and the parameter is the java configuration class
  • getBean gets the pojo object by configuring the method name of the class

8, Agent mode

1. Static proxy

Benefits:

  • It can make the operation of real roles more pure, without paying attention to some public businesses
  • The public business is handed over to the agent role, which realizes the division of business
  • When the public business is expanded, it is convenient for centralized management

Disadvantages:

  • A real role needs to create a proxy role, and the amount of code will become more
Code case

​ UserService:

public interface UserService {
    public void add();
    public void delete();
}

UserServiceImpl: real role

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("Called add method");
    }

    @Override
    public void delete() {
        System.out.println("Called delete method");
    }
}

​ UserProxy:

public class UserProxy 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();
    }

    public void log(String msg){
        System.out.println("[Debug] Added here" + msg + "journal!!");
    }
}

​ Test:

public class ClientDemo {
    @Test
    public void proxyTest(){
        //Before agency
        UserServiceImpl userService = new UserServiceImpl();
        userService.add();
        userService.delete();
		
        //After agency
        UserProxy userProxy = new UserProxy();
        userProxy.setUserService(userService);
        userProxy.add();
        userProxy.delete();
    }
}
Code explanation
  • UserService is an abstract interface that limits the specific methods to implement functions
  • UserServiceImpl is the implementation class of the interface, which implements the specific details of the function
  • UserProxy is a proxy class. Because it is necessary to add new functions without changing the original code, it still needs to implement the interface. Therefore, the specific implementation details of the new function can be defined in the proxy class, and then add a new function method to the rewriting method of the original function, and then call the method of the original implementation class to add new functions

2. Dynamic agent

Code case

User

// Common interface class
public interface User {
    void add();
    void query();
}

UserImpl

// Real role
public class UserImpl implements User{
    @Override
    public void add() {
        System.out.println("Added a user...");
    }

    @Override
    public void query() {
        System.out.println("Query all users...");
    }
}

ProxyInvocationHandler

// proxy class
public class ProxyClassDemo implements InvocationHandler {
    private Object target;

    public void setUser(Object target) {
        this.target = target;
    }

//    Generate a proxy class
    Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

//    Execute the method of the real role and return the execution result
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);
        other(method.getName());
        return result;
    }

//    Add log function
    public void other(String methodName){
        System.out.println("Yes " + methodName + " method...");
    }
}

Test

public class ClientDemo {
    public static void main(String[] args) {
//        new a real character
        Host host = new Host();
//        Generate proxy class
        ProxyClassDemo proxyClassDemo = new ProxyClassDemo();
//		  Class object passed in real character
        proxyClassDemo.setUser(host);
//        Force to public interface type
        Rent proxy = (Rent) proxyClassDemo.getProxy();
//        Calling methods of real objects
        proxy.money();
        proxy.rent();
    }
}
Code explanation
  • Dynamic agents are mainly divided into two categories:

    • Interface based dynamic agent

      • JDK dynamic proxy [used here]
    • Class based dynamic agent

      • cglib
    • Implementation based on java bytecode:

      • javasist
  • Dynamic proxy mainly needs two classes:

    • Proxy: generate proxy class
    • InvocationHandler: call handler
  • Method details of ProxyInvocationHandler class:

    • getProxy(): generate proxy class through proxy The newproxyinstance() static method dynamically obtains the proxy class
      • Proxy.newProxyInstance() :
        • Parameter 1: class loader of the current class, through this getClass(). Getclassloader()
        • Parameter 2: public interface, which is obtained through getInterfaces() of getClass() of the real role
        • Parameter 3: InvocationHandler, the class itself, because it implements the InvocationHandler interface
    • invoke(): call the class method of the real role and return the execution result
      • Directly call method Invoke () method and return the execution result
        • invoke():
          • Parameter 1: public interface class
          • Parameter 2: args

9, AOP [important]

It is suggested to save the image directly to the external link (tyim62626272image-68image / - 28mypop / config) (tyim72image-68image)

Three ways to implement AOP in spring

Facet class: the class that implements the extension method

[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-lhofegg-1622863598375) (/ home / Yijie /. Config / typora / typora user images / image-20210516225450025. PNG)]

  • No matter which of the following three methods, aop support needs to be enabled

    <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">
    </beans>
    
1.1 implementation of aop based on spring api

applicationContext.xml:

<bean id="userService" class="com.nari.demo1.service.UserServiceImpl"/>
    <bean class="com.nari.demo1.log.BeforeLog" id="beforeLog"/>
    <bean class="com.nari.demo1.log.AfterLog" id="afterLog"/>

    <aop:config>
		<!-- Set entry point-->
        <aop:pointcut id="pointcut" expression="execution(* com.nari.demo1.service.UserServiceImpl.*(..))"/>

        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

AfterLog: implements the AfterAdvice or AfterReturningAdvice interface. The difference is that there is a return value after the method is executed

public class AfterLog implements AfterReturningAdvice {
    /**
     *
     * @param returnValue   Method execution results
     * @param method        The method of the real class to execute
     * @param args          Method parameters
     * @param target        Common interface
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + " Yes " + method.getName() + " method,Return result:" + returnValue);
        for (int i = 0; i < 60; i++) {
            System.out.print("=");
        }
        System.out.println();
    }
}

BeforeLog:

public class BeforeLog implements MethodBeforeAdvice {
    /**
     *
     * @param method    The method of the real class to execute
     * @param args      Method parameters
     * @param target    Common interface
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + " Class executed " + method.getName() + " method");
    }
}

be careful:

  • Whether it is AfterAdvice, AfterReturningAdvice, MethodBeforeAdvice or BeforeAdvice, it inherits the Advice class

UserServiceImpl:

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("Added a user...");
    }

    @Override
    public void delete() {
        System.out.println("A user was deleted...");
    }
}

Test:

public class AOPDemo1 {
    @Test
    public void Demo1Test(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.add();
        userService.delete();
        userService.select();
    }
}
1.2 realize aop through user-defined classes

applicationContext.xml:

<!-- register bean -->
<bean id="addLog" class="com.nari.demo2.log.AddLog"/>
<bean id="bookService" class="com.nari.demo2.service.BookServiceImpl"/>

<!-- to configure aop -->
<aop:config>
    <!-- Configuration section, ref Is a custom facet class -->
    <aop:aspect ref="addLog">
        <!-- Set entry point -->
        <aop:pointcut id="pointcut" expression="execution(* com.nari.demo2.service.BookServiceImpl.*(..))"/>
        <!-- Configure cut in method -->
        <aop:before method="beforeLog" pointcut-ref="pointcut"/>
        <aop:after method="afterLog" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>

AddLog:

public class AddLog {
    public void beforeLog(){
        System.out.println("A log was added before the method was executed...");
    }

    public void afterLog(){
        System.out.println("A log was added after the method was executed...");
    }
}

BookServiceImpl:

public class BookServiceImpl implements BookService{
    @Override
    public void addBook() {
        System.out.println("Added a Book...");
    }

    @Override
    public void deleteBook() {
        System.out.println("Deleted a Book...");
    }
}

Test:

public class AOPDemo2 {
    @Test
    public void Demo2Test(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext2.xml");
        BookService bookService = applicationContext.getBean("bookService", BookService.class);
        bookService.addBook();
        bookService.deleteBook();
    }
}
1.3 realize aop by annotation

applicationContext.xml:

<!--    Enable annotation support-->
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.nari.demo2"/>
<context:annotation-config/>

annotationPointCut:

@Aspect
@Component
public class AnnotationPointCut {
    @Before("execution(* com.nari.demo2.service.BookServiceImpl.*(..))")
    public void beforeLog(){
        System.out.println("Method 3: before method implementation...");
    }

    @After("execution( * com.nari.demo2.service.BookServiceImpl.*(..))")
    public void afterLog(){
        System.out.println("Method 3: after method implementation...");
    }

    @Around("execution(* com.nari.demo2.service.BookServiceImpl.*(..))")
    public void aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Mode 3: surround the front...");
        joinPoint.proceed();
        System.out.println("Mode 3: surround the rear...");
        System.out.println(joinPoint.getKind());
        Signature signature = joinPoint.getSignature();
        System.out.println(signature.getName());
    }
}
  • joinPoint.proceed() executes the specific method

Test:

public class AOPDemo3 {
    @Test
    public void demo3Test(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext3.xml");
        BookService bookService = applicationContext.getBean("bookService", BookService.class);
        bookService.deleteBook();
    }
}

10, Integrate mybatis

  • Import the relevant jar package first
  • Writing pojo entity classes
  • Write interface
  • Write mapper configuration file
  • Writing spring configuration files
  • Write the interface implementation class, and use sqlSession to call the method in the implementation class

Dependent packages to import:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.5</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

<!-- aop Related dependency jar package -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.1</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.6</version>
</dependency>

<!-- integration mybatis Dependent packages -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>

<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>2.7.2</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.6</version>
</dependency>

spring-usermapper.xml:

<!-- dataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="url" value="jdbc:mariadb://localhost:3306/mybatis?characterEncoding=UTF-8&amp;useUnicode=true"/>
    <property name="driverClassName" value="org.mariadb.jdbc.Driver"/>
    <property name="username" value="root"/>
    <property name="password" value="ruirui"/>
</bean>

<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <!-- mapping Mapper configuration file -->
    <property name="mapperLocations" value="classpath:com/nari/mapper/UserMapper.xml"/>
</bean>

<!-- sqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>

<!-- register userMapper Interface implementation class bean,take sqlSession Inject in -->
<bean id="userMapper" class="com.nari.mapper.UserMapperImpl">
    <property name="sqlSession" ref="sqlSession"/>
</bean>

userMapperImpl:

@Setter
public class UserMapperImpl implements UserMapper{

    private SqlSessionTemplate sqlSession;
    @Override
    public List<User> selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

Test:

public class MybatisDemo1 {
    @Test
    public void test1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-usermapper.xml");
        UserMapper userMapper = applicationContext.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }
}

11, Business

Features: both successful and failed to ensure data integrity and consistency

ACID principle of transaction:

  • Atomicity
    • The smallest unit of a transaction. It cannot be split in a transaction. Operations in a transaction either occur or do not occur
  • uniformity
    • The integrity of the data before and after the transaction is committed must be consistent, that is, after the transaction is completed, it conforms to the logical operation
  • Isolation
    • When multiple businesses operate on the same resource, they are isolated. The operation of transaction A does not affect the operation of transaction B
  • persistence
    • Once the transaction is committed, no matter what happens, the result of the data will not be affected and will be persisted to the memory

1. Integrating mybatis with annotation

1.1 enable annotation support and annotation scanning
<context:component-scan base-package="com.narii"/>
<context:annotation-config/>
1.2 use notes
@Data
@Component("userMapper")
public class UserMapperImpl implements UserMapper {
    @Autowired
    @Qualifier("sqlSession")
    private SqlSessionTemplate sqlSession;

    @Override
    public List<UserPojo> queryUser() { ... }

2. Add transactions by faceting

<!-- Open declarative transaction -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- use spring Integration transaction -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- Configure propagation properties of transactions -->
    <tx:attributes>
        <!-- Add transactions to all methods -->
        <!-- There are many propagation characteristics of transactions, REQUIRED The default is to create a transaction if there is no transaction -->
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<!-- to configure aop -->
<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* com.narii.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>

Topics: Java Spring Java framework