Summary of AOP Learning in Spring Framework

Posted by nonaguy on Wed, 27 Nov 2019 01:49:00 +0100

@[toc] stay Spring Framework Learning 1 The main topics are some overviews of Spring, Spring factories, Spring attribute injection, and the introduction to IOC, the most important of which is IOC. Let's briefly summarize the IOC in the last article:

Then this article mainly talks about another important core in Spring besides IOC: AOP, IOC or AOP in Spring, both of which must be XML development and annotation development, that is, <font color=red>IOC and AOP XML development and annotation development must be mastered </font>

1. Overview of AOP

From a professional point of view (don't ask me how professional I am, Du Niang is not my cousin QAQ):

In the software industry, AOP is the abbreviation of Aspect Oriented Programming, which means facet-oriented programming, a technology for unified maintenance of program functions through precompilation and run-time dynamic agents.AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derived paradigm of functional programming.With AOP, parts of business logic can be isolated, which reduces the coupling between parts of business logic, improves the reusability of programs, and improves the efficiency of development.

From an easy-to-understand and interesting point of view: (from articles in Wuhan) Talk about IOC and AOP concepts in Spring)

The goal of face-oriented programming is to separate concerns.What is the focus?That's what you're going to do, that's what you're focusing on.If you are a dude, you have no goal in life. Every day you reach out for your clothes and your food. You only know one thing to play with all day!So, every day when you open your eyes, you just want to eat and play (what you have to do), but before you play, you also need to dress, wear shoes, fold quilts, cook, and so on. These things are your focus, but what if you just want to eat and play?These things are left to others.Before you reach the dining table, a special servant A helps you to dress, servant B helps you to wear shoes, servant C helps you to fold quilts, servant C helps you to cook, and then you start eating and playing (that's what you do all day). When you have finished your work, you come back, and a series of servants start to do this and that for you, and the day ends! The advantage of AOP is that you only need to do what you do, and others can do it for you.Maybe one day, if you want to run naked and don't want to wear clothes, you'll just dismiss your servant A!Maybe one day you want to bring some money before you go out, so you can hire another servant, D, to do the money work for you!This is AOP.Each person performs his or her own duties, and combines them flexibly to achieve a configurable and pluggable program structure. From Spring's point of view, the biggest use of AOP is to provide transaction management capabilities.Transaction management is a concern. Your business is to access the database and you don't want to be in charge of transactions (too annoying), so Spring automatically helps you start transactions before you access the database, and automatically commits/rolls back transactions when you finish accessing the database!

1.1 Why Learn AOP

Origin of Spring's AOP: AOP was originally proposed by the organization of AOP Consortium and a set of specifications was formulated. Spring brings AOP ideas into the framework and must abide by the specifications of AOP Consortium.

Aop solves some of the practical development issues:

  • AOP solves some problems encountered in OOP. It is the continuation and extension of OOP.

Enhancements to the program: Without modifying the source code:

  • AOP can perform privilege checking, logging, performance monitoring, and transaction control.

1, 2 AOP underlying implementation: proxy mechanism (understand)

The bottom level of Spring's AOP uses two proxy mechanisms:

  • Dynamic proxy for JDK: Proxy is generated for classes that implement interfaces.
  • Dynamic proxy for Cglib: Proxy generation for classes that do not implement interfaces. The underlying byte code enhancement technique is applied to generate subclass objects for the current class

The <font color=red>spring underlying layer completes the automatic proxy. Classes that implement interfaces default to the dynamic proxy of JDK. Conversely, classes that do not implement interfaces default to the dynamic proxy of Cglib </font>. The underlying code can not be understood, but this concept must be understood. Otherwise, it will be scorned, O() OHA~. Below is the underlying code, which is interesting to understand.Understand.

The JDK dynamic proxy enhances a method in a class:

public class MyJDKProxy implements InvocationHandler {
		private UserDao userDao;

		public MyJDKProxy(UserDao userDao) {
			this.userDao = userDao;
		}

		// Write tool method: Generate agent:
		public UserDao createProxy() {
			UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao
					.getClass().getClassLoader(), userDao.getClass()
					.getInterfaces(), this);
			return userDaoProxy;
		}

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			if ("save".equals(method.getName())) {
				System.out.println("Permission Check================");
			}
			return method.invoke(userDao, args);
		}
	}

The Cglib dynamic proxy enhances methods in a class:

public class MyCglibProxy implements MethodInterceptor {
		private CustomerDao customerDao;

		public MyCglibProxy(CustomerDao customerDao) {
			this.customerDao = customerDao;
		}

		// Method of generating proxy:
		public CustomerDao createProxy() {
			// Create the core class of Cglib:
			Enhancer enhancer = new Enhancer();
			// Set parent class:
			enhancer.setSuperclass(CustomerDao.class);
			// Set callback:
			enhancer.setCallback(this);
			// Generation agent:
			CustomerDao customerDaoProxy = (CustomerDao) enhancer.create();
			return customerDaoProxy;
		}

		@Override
		public Object intercept(Object proxy, Method method, Object[] args,
				MethodProxy methodProxy) throws Throwable {
			if ("delete".equals(method.getName())) {
				Object obj = methodProxy.invokeSuper(proxy, args);
				System.out.println("Logging================");
				return obj;
			}
			return methodProxy.invokeSuper(proxy, args);
		}
	}

2. Getting started with AOP development based on AspectJ (XML way):

First, why not do Spring develop AOP directly, but based on Aspectj? Because Spring's own AOP development implementation (traditional AOP development) is cumbersome, complex and inefficient, traditional AOP development is basically abandoned. On the contrary, Aspectj's AOP development is efficient, so AOP development is generally Spring's AspectJ-based AOP development.

2.1 Terms related to the development of AOP:

Aop is a very deep thought, and of course there will be very professional terms associated with it (which twists, how many points do you score?)

Overview definition from a professional perspective (relatively dull and difficult to understand):

<font color=red>Joinpoint</font>: Connection points are those that are intercepted.In spring, these points refer to methods, because spring only Connection points that support method types. <font color=red>Pointcut</font>: The entry point is the definition of which Joinpoint s we want to intercept. <font color=red>Advice </font>: Notification refers to what you do after intercepting a Joinpoint is a notification. Notification is divided into pre-notification and post-notification Notifications, Exception Notifications, Final Notifications, Surround Notifications (Functions to be completed in facets) <font color=red>Introduction</font>: Introduction is a special notification that an Introduction can be a class at run time without modifying the class code Add some methods or fields dynamically. <font color=red>Target </font>: Target object of proxy <font color=red>Weaving</font>: 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 and install-time weaving <font color=red>Proxy</font>: When a class is enhanced by AOP weaving, a result proxy class is generated <font color=red>Aspect </font>: A combination of entry points and notifications (introductions)

Instance-based analysis from a professional perspective (relatively easy to understand, what?Poor picture quality?Cough...1080p Blu-ray quality...Ouch..Big Brother..Don't hit...Don't hit...Don't hit your face:

2.2 Introducing appropriate jar packages

Introduce jar packages: base six jar packages, AOP Federation jar packages, spring's AOP jar packages, aspectJ's jar packages, spring's jar packages that integrate AspectJ

  • Packages for the development of spring's traditional AOP: spring-aop-4.2.4.RELEASE.jar com.springsource.org.aopalliance-1.0.0.jar

  • The development package for aspectJ: com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar

2.3 Introducing Spring's profile

Introduce AOP constraints:

 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

2.4 Writing target classes

Create interfaces and classes:

	public interface OrderDao {
		public void save();

		public void update();

		public void delete();

		public void find();
	}

	public class OrderDaoImpl implements OrderDao {
		@Override
		public void save() {
			System.out.println("Save Order...");
		}

		@Override
		public void update() {
			System.out.println("Modify Order...");
		}

		@Override
		public void delete() {
			System.out.println("Delete Order...");
		}

		@Override
		public void find() {
			System.out.println("Query orders...");
		}
	}

XML Configuration for 2.5 Target Class

<!--Target class configuration: Enhanced class--> 
<bean id="orderDao" class="com.gx.spring.demo3.OrderDaoImpl"></bean>

2.6 Integrating Junit Unit Tests

<font color=red>Prerequisite: By introducing the jar package of the spring-test.jar test, you do not need to register the factory repeatedly every time you integrate Junit unit tests. As long as you write two notes on the test class in a fixed format, you can inject the required attributes directly, and then only care about your test class</font>

//Fixed Annotation Writing (Prerequisite: introducing jar package for spring-test.jar test)
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath:applicationContext.xml")
	public class SpringDemo3 {
		@Resource(name = "orderDao")  //Required attribute injection directly (premise: introducing jar package for spring-test.jar test)
		private OrderDao orderDao;

		@Test
		public void demo1() {
			orderDao.save();
			orderDao.update();
			orderDao.delete();
			orderDao.find();
		}
	}

Running demo has the following effects:

2.7 Notification Type

At this point, you need to understand the type of notification (the first three are common):

Pre-notification: Executes before the target method executes. Post-notification: execute after target method execution <font color=red>If you want to get the return value in the post-notification, you must note that: </font> Wrap Notification: Execute before and after target method execution Exception throw notification: execute when the target method execution has an exception Final Notification: The final notification will be executed regardless of whether the target method has an exception or not.

Notification type XML configuration:

2.8 entry point expression

Execution (expression)

<font color=red>expression: [method access modifier] method return value package name. class name. method name (method parameter)</font>

The entry point expression is therefore execution([method access modifier] method return value package name. class name. method name (method parameter))

<font color=red>where method access modifiers in [] are available or not </font>

Examples of entry point expression types:

public * com.gx.spring.dao. * .*(..)
com.gx.spring.dao.*.*(..)
com.gx.spring.dao.UserDao+.*(..)
com.gx.spring.dao..*.*(..)

2.9 Write a tangent class

Now that you know the type of notification and the entry point expression, you can write a facet class to play with QAQ

public class MyAspectXml {
    // Pre-Enhancement
    public void before(){
       System.out.println("Pre-Enhancement===========");
} }

2.10 Configuration Complete Enhancement

<!-- Configure Face Class --> 
<bean id="myAspectXml" class="com.gx.spring.demo3.MyAspectXml"></bean>
<!-- Conduct aop Configuration --> 
<aop:config>
<!-- Configure entry point expressions:Which classes and methods need to be enhanced -->
 <aop:pointcut expression="execution(* com.gx.spring.demo3.OrderDao.save(..))" id="pointcut1"/>
<!-- Configure Faces --> 
<aop:aspect ref="myAspectXml"> 
    <aop:before method="before" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>

I've planned out all the things that need attention (don't boast me, I know I'm handsome QnQ)

2.11 Other enhanced configurations:

<!-- Configure Face Class -->
 <bean id="myAspectXml" class="com.gx.demo3.MyAspectXml"></bean>
	<!-- Conduct aop Configuration -->
 <aop:config>
	<!-- Configure entry point expressions:Which classes and methods need to be enhanced -->
	 <aop:pointcut expression="execution(* com.gx.spring.demo3.*Dao.save(..))" id="pointcut1"/>
	 <aop:pointcut expression="execution(* com.gx.spring.demo3.*Dao.delete(..))" id="pointcut2"/>
	 <aop:pointcut expression="execution(* com.gx.spring.demo3.*Dao.update(..))" id="pointcut3"/>
	 <aop:pointcut expression="execution(* com.gx.spring.demo3.*Dao.find(..))" id="pointcut4"/>
	<!-- Configure Faces --> 
	<aop:aspect ref="myAspectXml">
	   <aop:before method="before" pointcut-ref="pointcut1"/>
	   <aop:after-returning method="afterReturing"pointcut-ref="pointcut2"/>
	   <aop:around method="around" pointcut-ref="pointcut3"/>
	   <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4"/>
	   <aop:after method="after" pointcut-ref="pointcut4"/>
	</aop:aspect>
</aop:config>

3. Introduction to AOP development based on AspectJ by Spring (way of annotation):

3.1 Create a project and introduce jar packages

The following jar packages were introduced:

3.2 Introduction of configuration files

3.3 Write target classes and configure

Write the target class:

package com.gx.spring.demo1;

public class OrderDao {

	public void save(){
		System.out.println("Save Order...");
	}
	public void update(){
		System.out.println("Modify Order...");
	}
	public String delete(){
		System.out.println("Delete Order...");
		return "Cold";
	}
	public void find(){
		System.out.println("Query orders...");
	}
}

XML configuration:

<!-- Configure Target Class -->
	<bean id="orderDao" class="com.gx.spring.demo1.OrderDao">

	</bean>

3.4 Write the facet class and configure it

Write Face Class

package com.gx.spring.demo1;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * Tangent class: Note tangent class
 * @author jt
 */
public class MyAspectAnno {

	public void before(){
		System.out.println("Pre-Enhancement===========");
	}
}

XML configuration:

<!-- Configure Face Class -->
	<bean id="myAspect" class="com.gx.spring.demo1.MyAspectAnno">
	
	</bean>

3.5 Enhancement with annotated AOP object target class

1. Open annotated AOP development in configuration file

<!--Open annotated AOP development in configuration file-->
	<aop:aspectj-autoproxy/>

2. Use annotations on facet classes Use the @Aspect annotation on the class to indicate that this is a faceted class Injecting an attribute @Before (execution expression) into a method represents a preceding enhancement

@Aspect
public class MyAspectAnno {

	@Before(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	public void before(){
		System.out.println("Pre-Enhancement===========");
	}
}

3.6 Writing test classes

package com.gx.spring.demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Spring Annotation Development for AOP
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1 {
	@Resource(name="orderDao")
	private static OrderDao orderDao;
	
	public static void main(String[] args) {
		
			orderDao.save();
			orderDao.update();
			orderDao.delete();
			orderDao.find();
		
	}
	
}

Test results:

4. Notification type for Spring's annotated AOP

4.1@Before : Pre-notification

@Aspect
public class MyAspectAnno {

	@Before(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	public void before(){
		System.out.println("Pre-Enhancement===========");
	}
}

4.2@AfterReturning: Post Notification

Postnotification gets method return value

// Post Notification:
	@AfterReturning(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	public void afterReturning(Object result){
		System.out.println("Post Enhancement==========="+result);
	}

Borrowing an XML-style diagram means, or QnQ

4.3@Around : surround notification

// Surround notification:
	@Around(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("Enhancement before wrapping==========");
		Object obj  = joinPoint.proceed();
		System.out.println("Enhancement after wrapping==========");
		return obj;
	}

4.4@AfterThrowing: Exception throwing notification

Remember to make an abnormal qnq before testing

// Exception throw notification:
	@AfterThrowing(value="execution(* com.gx.spring.demo1.OrderDao.save(..))" throwing="e")
	public void afterThrowing(Throwable e){
		System.out.println("Exception throw enhancement========="+e.getMessage());
	}

4.5@After: Final Notification

// Final Notification
	@After(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	public void after(){
		System.out.println("Final Enhancement============");
	}

5. Configuration of entry points for Spring's annotated AOP

First of all, we find that in the process of introducing AOP development based on AspectJ in Spring, if there are too many methods, too many notifications and acting on a method, the corresponding source code needs to be changed as soon as the need changes. For better maintenance, with the configuration of AOP's entry point, the configuration of AOP's entry point can solve the problem well!You just need to manage the configuration of the AOP entry point!

The code is as follows:

package com.gx.spring.demo1;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * Tangent class: Note tangent class
 * @author jt
 */
@Aspect
public class MyAspectAnno {
	// Pre-notification:
	@Before(value="MyAspectAnno.pointcut2()")
	public void before(){
		System.out.println("Pre-Enhancement===========");
	}
	
	// Post Notification:
	@AfterReturning(value="MyAspectAnno.pointcut4()",returning="result")
	public void afterReturning(Object result){
		System.out.println("Post Enhancement==========="+result);
	}
	
	// Surround notification:
	@Around(value="MyAspectAnno.pointcut3()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("Enhancement before wrapping==========");
		Object obj  = joinPoint.proceed();
		System.out.println("Enhancement after wrapping==========");
		return obj;
	}
	
	// Exception throw notification:
	@AfterThrowing(value="MyAspectAnno.pointcut1()",throwing="e")
	public void afterThrowing(Throwable e){
		System.out.println("Exception throw enhancement========="+e.getMessage());
	}
	
	// Final Notification
	@After(value="MyAspectAnno.pointcut1()")
	public void after(){
		System.out.println("Final Enhancement============");
	}
	
	// Start Point Notes:
	@Pointcut(value="execution(* com.gx.spring.demo1.OrderDao.find(..))")
	private void pointcut1(){}
	@Pointcut(value="execution(* com.gx.spring.demo1.OrderDao.save(..))")
	private void pointcut2(){}
	@Pointcut(value="execution(* com.gx.spring.demo1.OrderDao.update(..))")
	private void pointcut3(){}
	@Pointcut(value="execution(* com.gx.spring.demo1.OrderDao.delete(..))")
	private void pointcut4(){}
}

If this article helps you a little, please give a compliment, thank you~

Finally, if there are any deficiencies or inaccuracies, you are welcome to correct the criticism and appreciate it!If in doubt, please leave a message and reply immediately!

Welcome to pay attention to my public number, discuss technology together, yearn for technology, and pursue technology. Well, you're friends now.

Topics: Programming Spring xml Junit