Three ideas of spring
IOC control reverse
DI dependency injection
AOP (Aspect Oriented Programming) makes up for the shortage of object-oriented programming
It is realized by precompiling and runtime dynamic agent
A technique for unified maintenance of sequential functions.
AOP is the continuation of OOP, a hot spot in software development, and an important part of Spring framework. Using AOP, we can make a clear understanding of business logic
The isolation of each part reduces the coupling degree between the parts of business logic, improves the reusability of the program, and improves the efficiency of development.
The benefits of doing so are:
- Enhance methods without modifying source code during program operation
- The logic is clear. When developing the core business, you don't need to pay attention to the code to enhance the business
- Reduce repetitive code, improve development efficiency and facilitate later maintenance
AOP related concepts
Target: the target object of the proxy
Proxy: when a class is enhanced by AOP weaving, a result proxy class is generated
Join point: the so-called join points refer to those intercepted points. In spring, these points refer to methods, because spring only supports connection points of method type
Pointcut: the so-called pointcut refers to the definition of which joinpoints we want to intercept
Advice (notification / enhancement): the so-called notification refers to the classification of notifications after intercepting Joinpoint: pre notification, post notification, exception notification, final notification and surround notification
Aspect: a combination of pointcuts and notifications
Weaving: refers to the process of applying enhancements to the target object to create a new proxy object. spring uses dynamic proxy weaving, while AspectJ uses compile time weaving and class load time weaving
OOP object oriented programming class
Let's take a brief look at aop through the code
Create a maven project
Implementation: call the service layer through the controller layer and then call the dao layer.
Create a maven project and lead the package (Note: change junit package version to 4.12 or higher),
Create a package level and run it to see if it can go through.
Create under resources applicationContext.xml configuration file
For example, create a bean class in the pojo package
package com.lanou.pojo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component(value = "user") public class User { @Value(value = "123") private int id; @Value("Zhang Sanfeng") private String username; @Value("123456") private String password; //setter getter with or without parameters toString method }
For example, dao layer
Interface
import com.lanou.pojo.User; import java.util.List; public interface UserDao { List<User> findAll(); User findUserById(int id); int updateUser(User user); int deleteUser(int id); }
Implementation class
import com.lanou.dao.UserDao; import com.lanou.pojo.User; import org.springframework.stereotype.Repository; import java.util.List; @Repository(value = "userDao") public class UserDaoImpl implements UserDao { @Override public List<User> findAll() { System.out.println("---------dao findAll Executed--------"); return null; } @Override public User findUserById(int id) { return null; } @Override public int updateUser(User user) { return 0; } @Override public int deleteUser(int id) { return 0; } }
For example, the service layer
import com.lanou.pojo.User; import java.util.List; public interface UserService { List<User> findAll(); User findUserById(int id); int updateUser(User user); int deleteUser(int id); }
service implementation class
import com.lanou.dao.UserDao; import com.lanou.pojo.User; import com.lanou.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.util.List; @Service(value = "userService") public class UserServiceImpl implements UserService { @Autowired @Qualifier(value = "userDao") private UserDao userDao; @Override public List<User> findAll() { return userDao.findAll(); } @Override public User findUserById(int id) { return null; } @Override public int updateUser(User user) { return 0; } @Override public int deleteUser(int id) { return 0; } }
For example: control layer
import com.lanou.pojo.User; import com.lanou.service.Impl.UserServiceImpl; import com.lanou.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import java.util.List; @Controller(value = "userController") public class UserController { @Autowired @Qualifier(value = "userService") private UserService userService; public void findAll(){ System.out.println("Before executing the current method"); List<User> userList = userService.findAll(); System.out.println("End of method execution"); } }
In the test class:
import com.lanou.controller.UserController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class TestSpringJUnit { @Autowired @Qualifier(value = "userController") private UserController userController; @Test public void findAll() { userController.findAll(); } }
Easy to walk
Section programming based on xml file
jar packages to be imported to use aop
spring-aop
spring-aspects
aopalliance
aspectjweaver
The dependent jar package will be imported automatically in maven
So you only need to find the two jar packages of spring aspects and aopalliance in maven library
<!--aop Required for tangent programming jar package--> <!--aop--> <!--aspects--> <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.1.14.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance --> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency>
Define a facet class in the utils package
/* Log facet class */ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //Declare that the current class is a tangent class public class LogAdvice { /* Section method Pre notification method */ public void before(){ System.out.println("--Before advice ----"); } /* Section method The post notification method returns whether it is abnormal or not */ public void after(){ System.out.println("--Post notice----"); } /* Post notification if exception does not return value */ public void afterReturning(){ System.out.println("---Post notice--No abnormality-"); } /* Post notification exception return */ public void afterException(){ System.out.println("--Post notice--Exception notification--"); } /* Around Advice */ public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println("Around Advice --Before advice "); Object object = point.proceed();//Continue calling target method System.out.println("Around Advice --Post notice"); return object; } }
Configuring in an xml configuration 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: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 https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:annotation-config></context:annotation-config> <context:component-scan base-package="com.lanou"></context:component-scan> <!--Define section information--> <bean id="logAdvice"></bean> <!--Defining entry points--> <aop:config> <!-- //breakthrough point id : name expression : Expression found package, class, method execution(* com.lanou.service.*.*(..)) //Return value type of the first * method com.lanou.service Package name //Second * class name //Third * method name (..) Any parameter --> <aop:pointcut id="pc" expression="execution(* com.lanou.service.*.*(..))"/> <!--Define associated facets--> <aop:aspect ref="logAdvice"> <aop:before method="before" pointcut-ref="pc"></aop:before> <aop:after method="after" pointcut-ref="pc"></aop:after> <aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning> <aop:after-throwing method="afterException" pointcut-ref="pc"></aop:after-throwing> <aop:around method="around" pointcut-ref="pc"/> </aop:aspect> </aop:config> </beans>
Running the test method in the test class can see that the pre notification is performed before the core logic is executed, and the circular notification is performed. oop feels vertical, but aop seems to cut you horizontally. In addition to the enhanced business you want to perform (pre notification belongs to enhanced business), you need to perform pre business before performing core business (dao findAll core business)
Annotation based AOP
Open annotation in xml file
(Note: when I open annotation, I give the annotation the xml configuration, because when I test, I feel that the priority of xml configuration is higher than that of annotation.)
<!--open aop annotation--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
Annotate LogAdvice in utils package
/* Log facet class */ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component(value = "logAdvice") //Declare that the current class is a tangent class @Aspect public class LogAdvice { /* If the expressions are the same, you don't need to configure anything else, You can add @ Pointcut("execution(* com.lanou.service .*.*(..))") Comments to be added every time around“ LogAdvice.pc() "you don't have to configure it every time */ @Pointcut("execution(* com.lanou.service.*.*(..))") public void pc(){ } /* Section method Pre notification method Every time you have to follow an expression, do you have a method? If the expressions are the same, you don't need to configure other */ @Before("LogAdvice.pc()") public void before(){ System.out.println("--Before advice ----"); } /* Section method The post notification method returns whether it is abnormal or not */ @After("execution(* com.lanou.service.*.*(..))") public void after(){ System.out.println("--Post notice----"); } /* Post notification if exception does not return value */ @AfterReturning("execution(* com.lanou.service.*.*(..))") public void afterReturning(){ System.out.println("---Post notice--No abnormality-"); } /* Post notification exception return */ @AfterThrowing("execution(* com.lanou.service.*.*(..))") public void afterException(){ System.out.println("--Post notice--Exception notification--"); } /* Around Advice */ @Around("execution(* com.lanou.service.*.*(..))") public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println("Around Advice --Before advice "); Object object = point.proceed();//Continue calling target method System.out.println("Around Advice --Post notice"); return object; } }
Call test method: configuration in xml is an effect