Spring Aop will take you step-by-step.

I wonder, too, about the recent enthusiasm of bloggers for blogging: Why? In the Age of the Internet, no matter you are talented or inexperienced, you have the right to express your opinions. Whether you’re right or wrong, you’ll find out on this platform. Therefore, I will try my best to write what I am interested in, no matter positive or negative news, and try my best to reply to every one of my readers. Even if I only have one reader, I will keep writing. Isn’t it a kind of happiness to have a platform to express and record yourself? Similarly, understanding technology is a deep and expansive process that requires one’s clear and rigorous logical thinking. Sometimes, blogging is more like taking notes for yourself and consolidating scattered knowledge!

This article is a complement to the last article in which I discussed the spring source code. Getting back to the point, why is there AOP? We know Java is an object-oriented language (OOP), but it has some disadvantages, such as when we need for multiple objects to inherit relationship with the introduction of a public behavior, such as logging, authentication, transactions, and other functions, can only be in each object reference public behavior, to do so is not easy to maintain, and there are a lot of duplicate code. AOP has made up for this shortcoming of OOP.

To clarify Spring AOP, let’s discuss it from the following aspects:

  1. Proxy mode.
  2. Principle and practice of static proxy.
  3. Dynamic proxy principle and practice.
  4. Principle and practice of Spring AOP.

1. Proxy mode.

Proxy mode: Provides a proxy for other objects to control access to that object. This paragraph is quite official, but I prefer to use my own language to understand it: for example, if object A wants to do something, it will do it by itself before there is no proxy, and after A is the proxy class B of A will do it. Proxying is essentially adding a layer of processing before and after the original instance, which is AOP’s primary contours.

2. Principle and practice of static proxy.

Static proxy mode: Static proxy means that the bytecode file of the proxy class exists before the program runs, and the relationship between the proxy class and the original class is determined before the program runs. Without further discussion, let’s take a look at the code. To make it easier to read, the blogger merges a separate class file into the interface, and readers can directly copy the code to run:

package test.staticProxy;
/ / interface
public interface IUserDao {
	void save(a);
	void find(a);
}
// Target object
class UserDao implements IUserDao{
	@Override
	public void save(a) {
		System.out.println("Simulation: Save the user!");
	}
	@Override
	public void find(a) {
		System.out.println("Simulation: Query user");
	}
}
/ * *
Static agent
Features:
1. The target object must implement the interface
2. Proxy object, to implement the same interface as the target object
* /
class UserDaoProxy implements IUserDao{
	// Proxy object, need to maintain a target object
	private IUserDao target = new UserDao(a);
	@Override
	public void save(a) {
		System.out.println("Agent operation: Start transaction...");
		target.save(a);   // Execute the target object's method
		System.out.println("Agent action: Commit transaction...");
	}
	@Override
	public void find(a) {
		target.find(a);
	}
}
Copy the code

Test results:

A static proxy ensures that the business class only needs to focus on the logic itself, and that an interface of the proxy object serves only one type of object. If there are many methods to be propped, it is necessary to propped for each method. Furthermore, if you add a method, all proxy classes need to implement the method in addition to the implementation class. Increased code maintenance costs. So how to solve it? The answer is to use dynamic proxies.

3. Dynamic proxy principle and practice

Dynamic proxy mode: The source code for dynamic proxy classes is generated dynamically during program execution through mechanisms such as JVM reflection, and the relationship between proxy classes and delegate classes is determined at runtime. Examples are as follows:

package test.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/ / interface
public interface IUserDao {
	void save(a);
	void find(a);
}
// Target object
 class UserDao implements IUserDao{
	@Override
	public void save(a) {
		System.out.println("Simulation: Save the user!");
	}
	@Override
	public void find(a) {
		System.out.println("Query");
	}
}
/ * *
* Dynamic proxy:
* Proxy factory, generate proxy objects for multiple target objects!
 *
* /
class ProxyFactory {
	// Receive a target object
	private Object target;
	public ProxyFactory(Object target) {
		this.target = target;
	}
	// Return the target object after the proxy.
	public Object getProxyInstance(a) {
		Object proxy = Proxy.newProxyInstance(
			target.getClass().getClassLoader(),  // The class loader used by the target object
			target.getClass().getInterfaces(),   // All interfaces implemented by the target object
			new InvocationHandler(a) {			// When the proxy object method is executed
				@Override
				public Object invoke(Object proxy. Method method. Object[] args)
						throws Throwable {

					// Gets the method name of the currently executing method
					String methodName = method.getName(a);
					// The method returns a value
					Object result = null;
					if ("find".equals(methodName)) {
						// Call the target object method directly
						result = method.invoke(target. args);
					} else {
						System.out.println("Open transaction...");
						// Execute the target object method
						result = method.invoke(target. args);
						System.out.println("Commit transaction...");
					}
					return result;
				}
			}
		);
		return proxy;
	}
}
Copy the code

The test results are as follows:

In the code that creates test class objects in the run test class

IUserDao proxy = (IUserDao)new ProxyFactory(target).getProxyInstance(a);
Copy the code

Instead, the JDK dynamically generates a class to implement the interface, hiding the process:

class $jdkProxy implements IUserDao{}
Copy the code

The premise of using dynamic proxies generated by the JDK is that the target class must have an interface to implement. The Cglib proxy is the solution to the problem that JDK dynamic proxies cannot be used if a class does not implement an interface.

Cglib is implemented with a dynamically generated subclass inheritance goal, dynamically building a subclass in memory at runtime as follows:

public class UserDao{}
//Cglib is implemented as a dynamically generated subclass inheritance target. The following process is hidden when the program executes
public class $Cglib_Proxy_class  extends UserDao{}
Copy the code

Cglib is used on the premise that the target class cannot be final. Because final modified classes cannot be inherited.

Now let’s look at the definition of AOP: section-oriented programming, the core principle of which is to use the dynamic proxy pattern to add logic before and after method execution or when exceptions occur.

From the definition and the previous code we can see three things:

  1. AOP is based on the dynamic proxy pattern.
  2. AOP is method-level (the method to be tested cannot be static because static methods cannot exist in the interface and will be reported as an error by compilation).
  3. AOP can separate business code from concern code (duplicate code) and inject concern code dynamically as business code is executed. The aspect is the class formed by the code of concern.

4. Principle and practice of Spring AOP

As mentioned above, the JDK proxy and the Cglib proxy are two dynamic proxies. The excellent Spring framework integrates both approaches in the bottom layer, so we don’t need to worry about implementing dynamic proxies ourselves. So how does Spring generate proxy objects?

  1. When the container object is created, the proxy object is generated based on the class that the pointcut expression intercepts.
  2. If the target object has an implementation interface, use a JDK proxy. If the target object does not implement an interface, the Cglib proxy is used. It then gets the proxied object from the container and implants the methods of the “aspect” class at run time. In the DefaultAopProxyFactory class, we can find this statement in the Spring source code.

The simple fact is, if you have an interface, use a Jdk proxy, and if you don’t, use Cglib, which is exactly what I said earlier. If the target class does not implement an interface, and the class is final, then spring AOP cannot be programmed!

With that in mind, we’ll now implement Spring AOP manually ourselves:

package test.spring_aop_anno;

import org.aspectj.lang.ProceedingJoinPoint;

public interface IUserDao {
	void save(a);
}
// Test the Cglib dynamic proxy
class OrderDao {
	public void save(a) {
		//int i =1/0; Used to test exception notifications
		System.out.println("Save order...");
	}
}
// Used to test JDK dynamic proxies
class UserDao implements IUserDao {
	public void save(a) {
		//int i =1/0; Used to test exception notifications
		System.out.println("Save user...");
	}
}
/ / cut class
class TransactionAop {
	public void beginTransaction(a) {
		System.out.println("[Pre-notification] Start transaction..");
	}
	public void commit(a) {
		System.out.println("[Post notification] Submission transaction..");
	}
	public void afterReturing() {
		System.out.println("[Notification upon return]");
	}
	public void afterThrowing() {
		System.out.println("[Exception Notification]");
	}
	public void arroud(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("[Around front:]");
		pjp.proceed(a);    			   // Execute the target method
		System.out.println([After wrapping:]");
	}
}
Copy the code

XML configuration file for Spring:


        
<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/aop/spring-aop.xsd">
	<! Add dao instance to container -->
	<bean id="userDao" class="test.spring_aop_anno.UserDao"></bean>

	<! Add dao instance to container -->
	<bean id="orderDao" class="test.spring_aop_anno.OrderDao"></bean>

	<! -- Instantiate the section class -->
	<bean id="transactionAop" class="test.spring_aop_anno.TransactionAop"></bean>

	<! -- Aop related configuration -->
	<aop:config>
		<! Pointcut expression definition -->
		<aop:pointcut expression="execution(* test.spring_aop_anno.*Dao.*(..) )" id="transactionPointcut"/>
		<! -- Section Configuration -->
		<aop:aspect ref="transactionAop">
			<! -- [circular notification] -->
			<aop:around method="arroud" pointcut-ref="transactionPointcut"/>
			<! -- [pre-notification] execute before target method -->
			<aop:before method="beginTransaction" pointcut-ref="transactionPointcut" />
			<! -- [post notification] -->
			<aop:after method="commit" pointcut-ref="transactionPointcut"/>
			<! -- [Notification upon return] -->
			<aop:after-returning method="afterReturing" pointcut-ref="transactionPointcut"/>
			<! -- Exception notification -->
			<aop:after-throwing method="afterThrowing" pointcut-ref="transactionPointcut"/>
		</aop:aspect>
	</aop:config>
</beans>      
Copy the code

Pointcut expressions are not covered here. Ref :Spring AOP pointcut expression

The code test results are as follows:

Now that we’ve covered spring AOP, we return to our opening question: What do we do with it?

  1. Spring declarative transaction management configuration, another article: Distributed system Architecture demo: SSM + Dubbo
  2. Parameter verification of the Controller layer. Ref: Spring AOP intercepts Controller for parameter verification
  3. Use Spring AOP to implement MySQL database read and write separation case analysis
  4. Before executing a method, determine whether permissions are available.
  5. Log calls to some functions. Monitor some important functions. If a specified exception is thrown, relevant personnel can be notified by SMS or email.
  6. Information filtering, page forwarding and other functions, the power of a blogger is limited, can only list so many, welcome to the comment section to supplement the article.

What can spring AOP do, what magic function to achieve, is that we each ordinary and wise ape program!

The original:What is Spring AOP? What do you do with it?