An in-depth analysis of spring's AOP implementation principles _java

Source: Internet
Author: User
Tags aop exception handling inheritance reflection throwable

What is AOP

AOP (aspect-orientedprogramming, aspect-oriented programming) can be added and perfected by OOP (object-oriented programing, object-oriented programming). OOP introduces concepts such as encapsulation, inheritance, and polymorphism to create an object hierarchy to simulate a set of public behaviors. Oop seems powerless when we need to introduce public behavior for dispersed objects. In other words, OOP allows you to define a relationship from top to bottom, but it is not appropriate to define a relationship from left to right. such as logging functions. The log code tends to spread horizontally across all object hierarchies and has nothing to do with the core functionality of the objects it spreads to. This is true for other types of code, such as security, exception handling, and the persistence of transparency. This scattered, unrelated code is called crosscutting (cross-cutting) code, which, in OOP design, results in a lot of code duplication, which is not conducive to the reuse of each module.

Brief introduction

The Java design pattern--proxy mode, which was written some time ago--recently, when looking at spring AOP, felt that the agent model should be closely related, and decided to understand the implementation of Spring AOP.

Speaking of AOP, we have to talk about OOP. In OOP, concepts such as encapsulation, inheritance and polymorphism are introduced to establish an object hierarchy to simulate a set of public behaviors. However, if we need to introduce a common part for some objects, OOP introduces a lot of repetitive code. For example: Log function.

AOP Technology leverages a technology called "crosscutting", the interior of the encapsulated objects and the public behavior that affects multiple classes is encapsulated into a reusable module, which reduces the system's duplication of code, reduces the coupling between modules, and facilitates future operability and maintainability. AOP divides software systems into two parts: core concerns and crosscutting concerns. The main process of business processing is the core concern, and the part that does not relate to it is crosscutting concerns. One of the features of crosscutting concerns is that they often occur at many points in the core focus and are basically similar in every place. such as permission authentication, log, transaction processing.

Implementation principle 

In the previous Learning Agent mode, I understand that the agent model is divided into dynamic agents and static agents. Now we're going to implement our own AOP framework based on agent mode, and then we'll look at the implementation principles of Spring's AOP.

As a static proxy, the key is to implement a common interface between the proxy object and the target object, and the proxy object holds the reference of the target object.

  Common Interface Code:

Public interface Ihello {
/**
* Business Method
* @param str
/void SayHello (String str); 
Target Class Code: Public

class Hello implements ihello{
@Override public
void SayHello (String str) {
System.out.println ("Hello" +str);
}

Proxy class Code, we have to add logging to it, the method before and after the implementation of a specific method, is not like AOP special?

public class Proxyhello implements ihello{ 
private Ihello hello; 
Public Proxyhello (Ihello hello) {
super ();
This.hello = hello;
}
@Override public
void SayHello (String str) {
logger.start ();//Add a specific method
Hello.sayhello (str);
Logger.end ();
}

  Log Class Code:

public class Logger {public
static void Start () {
System.out.println (new Date () + "Say hello start ...");
} Public
static void End () {
System.out.println (new Date () + ' Say hello end ');
}

  Test code:

public class Test {public
static void Main (string[] args) {
Ihello hello = new Proxyhello (new Hello ());//If we need Log function, then use the proxy class
//ihello hello = new Hello ();//If we do not require logging functionality, use the target class
Hello.sayhello ("Tomorrow"); 
}

This allows us to implement one of the simplest AOP, but there's a problem: if we have a lot of classes like Hello, are we going to write a lot of helloproxy classes? In fact, it is also a very troublesome matter. After jdk1.3, the JDK provides us with an API Java.lang.reflect.InvocationHandler class that lets us dynamically do something about the methods of a class when the JVM invokes it. Here we will implement the dynamic proxy implementation.

Dynamic proxy implementation is mainly to implement Invocationhandler, and inject target object into proxy object, using reflection mechanism to execute target object's method.

Interface implementations are the same as static proxies, proxy class code:

public class Dynaproxyhello implements invocationhandler{
Private object target;//target object
/**
* Instantiating the target object by reflection
* @param object
* @return
/public object bind (object) {
This.target = object;
Return Proxy.newproxyinstance (This.target.getClass (). getClassLoader (), This.target.getClass (). Getinterfaces (), this);
}
@Override Public
object Invoke (Object proxy, Method method, object[] args)
throws Throwable {
object result = NULL;
Logger.start ()//Add an additional method
//The method of running the target object by reflection mechanism result
= Method.invoke (This.target, args);
Logger.end ();
return result;
}

Test Class Code:

public class Dynatest {public
static void Main (string[] args) {
Ihello hello = (ihello) new Dynaproxyhello (). Bi nd (new Hello ());//If we need a log function, then use the proxy class
//ihello hello = new Hello ();//If we do not require logging functionality, use the target class
Hello.sayhello ("Tomorrow") ;
}
}

After reading the above code may have a problem with spring AOP, the log class can only be printed before and after the method, but AOP should be able to meet the conditions can be executed, all can be Dynapoxyhello object and log Operations object (Logger) decoupling it?

Look at the following code implementation to decouple the Dynapoxyhello object and the Log Operations object (Logger):

We want to add the log operation code (or other code of operation) to the method of the proxy object before or after it. So, we can abstract an interface in which there are only two methods: A method that executes before the proxy object executes the method, and we name the start. The second method is the method that executes after the proxy object executes the method, which we name as end.

  Logger interface:

Public interface ILogger {"
void start");
void End (Method method);

 Logger Interface Implementation:

The public class Dlogger implements ilogger{@Override the public
void Start (Method method) {
System.out.println ( New Date () + method.getname () + "Say hello start ...");
}
@Override public void End (method method
) {
System.out.println (new Date () + method.getname () + ' Say hello end ');
}
}

Dynamic proxy class:

public class Dynaproxyhello implements invocationhandler{
//Calling object
private object proxy;
Target object
private object target;
public object bind (Object Target,object proxy) {
this.target=target;
This.proxy=proxy;
Return Proxy.newproxyinstance (This.target.getClass (). getClassLoader (), This.target.getClass (). Getinterfaces (), this);
}
@Override Public
object Invoke (Object proxy, Method method, object[] args)
throws Throwable {
object result = NULL;
Reflection gets the operator's instance
Class clazz = This.proxy.getClass ();
The Start method that reflects the operator is start
= Clazz.getdeclaredmethod ("Start", new Class[]{method.class});
The reflection executes the Start Method
Start.invoke (This.proxy, New Object[]{this.proxy.getclass ()});
Executes the original method of the object to be processed
method.invoke (this.target, args);
Reflection gets the operator's end methods method End
= Clazz.getdeclaredmethod ("End", new Class[]{method.class});
Reflection execution End Method
End.invoke (This.proxy, New Object[]{method});
return result;
}

  Test code:

public class Dynatest {public
static void Main (string[] args) {
Ihello hello = (ihello) new Dynaproxyhello (). bind (New Hello (), new Dlogger ());//If we need a log function, then use the proxy class
//ihello hello = new Hello ();//If we don't need logging, use the target class
Hello.sayhello ("Tomorrow");

Through the example above, it can be found that through dynamic Proxy and launch technology, has basically implemented the functions of AOP, if we only need to print the log before the method execution, you can not implement the end () method, so you can control the timing of printing. If we want the specified method to print the log, we only need to add a judgment to the name of the method in the invoke () approach, and the name of methods can be written in the XML file so that we can implement the decoupling of the configuration file so that we implement a simple spring AOP Framework.

The above content is small to introduce the spring of the introduction of the AOP principle, I hope to help you!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.