Reprint Address: https://my.oschina.net/elain/blog/382494 One, 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 (logs, security, and transactions) 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 extraneous code, scattered around the globe, is called crosscutting (cross-cutting) code, which, in OOP design, results in a lot of code duplication and a high degree of coupling between modules, which is not conducive to the reuse of modules.
AOP technology, on the contrary, uses a technique called crosscutting to unpack the encapsulated objects and encapsulate the public behavior that affects multiple classes into a reusable module called "Aspect", or slice. The so-called "cut", simply, is that those with the business, but the common call for business modules of the logic or responsibility to encapsulate, easy to reduce system duplication of code, reduce the coupling between modules, and conducive to future operability and maintainability. AOP represents a horizontal relationship, if "object" is a hollow cylinder, which encapsulates the object's properties and behavior, so the aspect-oriented programming approach, like a razor, cuts these hollow cylinders open to get inside the message. And cut the cut, which is called "aspect". Then it will be skillfully seize the hands of the hands of the cut off the cutting surface of the surface recovery, without leaving traces.
Using crosscutting technology, AOP divides software systems into two parts: core business logic Components and crosscutting concerns. Crosscutting concerns are modeled as special classes, which are called "slices," benefits: 1. Crosscutting concerns are concentrated in one piece with no significant duplication of code; 2. Core modules focus on the core functions of the code, the coupling between the modules to reduce.
Second, the realization principle of AOP
As shown in the figure: AOP is actually implemented by the proxy class of the target class. An AOP broker is actually an object that is dynamically generated by the AOP framework and can be used as a target object. The AOP agent contains all the methods of the target object, but the methods in the AOP agent differ from the methods of the target object, and the AOP method adds enhanced processing to the specific pointcut and callbacks the method of the target object.
Iii. AOP-related concepts
Connection point (Joinpoint): a particular point in the execution of a program, such as when a method is invoked or when an exception is handled. In spring AOP, a connection point always represents the execution of a method. In layman's parlance, the point where the tangent is added.
Notification (Advice): An action that is performed on a particular connection point in the slice. These include different types of notifications such as "Around", "before", and "after" (the type of notification will be discussed later). Many AOP frameworks, including spring, use interceptors as notification models and maintain a chain of interceptors centered on connection points.
Pointcut (Pointcut): an assertion that matches a connection point. A notification is associated with a pointcut expression and runs on a connection point that satisfies the pointcut (for example, when a method of a particular name is executed). How Pointcut expressions match connection points is at the heart of AOP: Spring defaults to using ASPECTJ pointcut syntax.
Introduction (Introduction): Used to declare an additional method or property (also known as a connection type declaration (Inter-type declaration)) for a type. Spring allows the introduction of a new interface (and a corresponding implementation) to any object that is being represented. For example, you can use the introduction to enable a bean to implement the IsModified interface to simplify caching mechanisms.
Weaving: The process of applying a slice to a target object to create a new proxy object. These can be done at compile time (for example, using the ASPECTJ compiler), when the class is loaded, and at run time. Spring, like other pure Java AOP frameworks, completes weaving at run time.
Enhancements (Advice): A piece of code that is woven into a target class connection point. Spring uses an enhanced class to define crosscutting logic, and since spring only supports method connection points, enhancements also include information about where to add crosscutting code to the method, so enhancements include both crosscutting logic and partial connection points.
Introduction (Introduction): is a special enhancement that adds some properties and methods to the class.
Section (Advisor): Represents a General section, contains the crosscutting code and the connection point information, itself is a simple section, the crosscutting connection point is all the methods of the target class. 3 Types: General section (advisor), tangent plane (pointcutadvisor), Introduction section (Introductionadvisor).
Iv. implementation of AOP in spring
The first is based on the implementation of the XML configuration file method,
The second is based on the annotation method implementation.
First, let's take a look at the Business logic service layer:
/**
* Registerservice Implementation class
* @author Cao Sheng Huan */Public
class Registerserviceimpl implements Registerservice {
Private Registerdao Registerdao;
Public Registerserviceimpl () {}
/** construction method with parameters *
/Public Registerserviceimpl (Registerdao Registerdao) {
This.registerdao =registerdao;
}
public void Save (string loginname, string password) {
registerdao.save (loginname, password);
throw new RuntimeException ("intentionally throws an exception ....") ");
}
/** Set Method *
/public void Setregisterdao (Registerdao registerdao) {
This.registerdao = Registerdao;
}}
For a business system, the Registerserviceimpl class is the target implementation class, and its business methods, such as before or after the Save () method, or where the code will appear to be abnormal, are AOP connection points.
The following is the code for the Log service class:
/** * Log Slice class * @author Cao Sheng Huan */public class Logaspect {//Any notification method can define the first parameter as a org.aspectj.lang.JoinPoint type public void before (Joinpoint call) {//Get the target object's corresponding class name String ClassName = Call.gettarget (). GetClass (). g
Etname ();
Gets the method name String methodname = Call.getsignature () that is executing on the target object. GetName ();
SYSTEM.OUT.PRINTLN ("predecessor Notice:" + className + "class" + MethodName + "method started");
public void Afterreturn () {System.out.println ("Post notification: Method ends normally");
public void After () {System.out.println ("Final Notice: no matter whether the method is performed properly, it will return");
public void afterthrowing () {System.out.println ("Notification after exception is thrown: unexpected when method executes"); The method used for wrapping notifications can be defined as the Org.aspectj.lang.ProceedingJoinPoint type public Object doaround the first parameter (Proceedingjoinpoint call
) throws Throwable {Object result = null;
This.before (call);//corresponds to the predecessor notification try {result = Call.proceed (); This.afterrEturn (); Equivalent to post notification} catch (Throwable e) {this.afterthrowing ();
Equivalent to the exception thrown after the notification throw e; }finally{This.after ();
Equivalent to final notice} return result; }
}
This class belongs to the business service class, which, if used in AOP terms, is a slice class that defines many notifications. Before (), Afterreturn (), after () and afterthrowing () are notifications.
Here we look at the specific configuration, first look at:
<1> AOP implementation based on XML configuration files: This approach has 4 steps when implementing AOP.
<?xml version= "1.0" encoding= "UTF-8"?> <beans xmlns= "Http://www.springframework.org/schema/beans" xml
Ns: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/be Ans/spring-beans-2.5.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP /spring-aop-2.5.xsd> <bean id= "Registerdaoimpl" class= "Com.zxf.dao.RegisterDaoImpl"/> <bean id= "re Gisterservice "class=" Com.zxf.service.RegisterServiceImpl "> <property name=" Registerdaoimpl "ref=" Regis Terdaoimpl "/> </bean> <!--log slicing class--> <bean id=" Logaspectbean "class=" COM.ZXF.ASPECT.L Ogaspect "/> <!--step 1th: AOP configuration--> <aop:config> <!--2nd step: Configure a slice--> ; Aop:aspect id= "LogaspecT "ref=" Logaspectbean > <!--step 3rd: Define pointcuts, specify Pointcut expressions--> <aop:pointcut id= "Allmethod" expression= "Execution (* com.zxf.service.*.* (..))"
/> <!--step 4th: Apply--> <aop:before method= "before" pointcut-ref= "Allmethod"/> <!--step 4th: Apply post notification--> <aop:after-returning method= "Afterreturn" pointcut-ref= "Allmetho"
D "/> <!--4th step: Application of the final notice--> <aop:after method=" after "pointcut-ref=" Allmethod "/> <!--step 4th: Notify--> <aop:after-throwing method= "afterthrowing pointcut-ref=" after the application throws an exception Allmet Hod "/> <!--step 4th: Apply Surround Notification--> <!--<aop:around method=" Doaround "poi ntcut-ref= "Allmethod"/>--> </aop:aspect> </aop:config> </beans>
The above configuration applies the front, rear, final, and notification after the pointcut has been thrown. This way, when testing the Save () method for executing the Registerserviceimpl class, the console has the following result output:
Predecessor notification: The Save method for the Com.zxf.service.RegisterServiceImpl class begins.
The Save () method in the Registerdao implementation of MySQL.
Post notification: The method ends normally.
Final notification: Whether or not the method is performed properly, it will be returned.
Now let's look at the second configuration:
<2> implementation of annotation-based AOP
Start by creating a class logannotationaspect to use as a slice, and configure this class in the spring configuration file.
The support of the JDK5.0 annotation annotation was introduced after spring2.0, providing support for ASPECTJ based on the annotation section to further simplify the configuration of AOP. There are two steps to the concrete step.
The configuration file for spring is the following configuration:
<?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:aop= "http://www.springframework.org/ SCHEMA/AOP "
xsi:schemalocation="
http://www.springframework.org/schema/beans http:// Www.springframework.org/schema/beans/spring-beans-2.5.xsd
HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http:// www.springframework.org/schema/aop/spring-aop-2.5.xsd>
<bean id= "Registerdao" class= " Com.zxf.dao.RegisterDaoImpl "/> <bean id= registerservice" class= "Com.zxf.service.RegisterServiceImpl"
>
<property name= "Registerdao" ref= "Registerdao"/>
</bean>
<!--the Slice class is managed by the spring container- ->
<bean id= "Logaspectbean" class= "Com.zxf.aspect.LogAnnotationAspect"/>
<!-- Enable spring support for ASPECTJ annotations-->
<aop:aspectj-autoproxy/>
</beans>
This is the class logannotationaspect of that slice.
/** * Log Slice class/@Aspect//Define slice class public class Logannotationaspect {@SuppressWarnings ("unused")//define Pointcuts
, providing a method whose name is the ID of the pointcut @Pointcut ("Execution (* com.zxf.service.*.* (..))")
Application of the predecessor Notification @Before ("execution (* com. zxf.service.*.* (..))") for the pointcut selected by the specified pointcut expression, private void Allmethod () {})
public void before (Joinpoint call) {String className = Call.gettarget (). GetClass (). GetName ();
String methodname = Call.getsignature (). GetName ();
System.out.println ("Annotation-Front notice": "+ ClassName +" class "+ MethodName +" method started "); ///access named Pointcut to apply the post notification @AfterReturning ("Allmethod ()") public void Afterreturn () {System.out.print
ln ("" Annotation-Post Notice ": Method ends normally"); //Apply Final notification @After ("Allmethod ()") public void After () {System.out.println ("annotation-Final Notice": whether or not the method is normal
The line completes, "+" will certainly return "); Notify @AfterThrowing ("Allmethod ()") public void a after applying exception thrownFterthrowing () {System.out.println ("" Note-Notification after exception is thrown: An exception occurred when the method was executed);
//apply around notification//@Around ("Allmethod ()") Public Object Doaround (Proceedingjoinpoint call) throws throwable{
Object result = null;
This.before (call);//corresponds to the predecessor notification try {result = Call.proceed (); This.afterreturn (); Equivalent to post notification} catch (Throwable e) {this.afterthrowing ();
Equivalent to the exception thrown after the notification throw e; }finally{This.after ();
Equivalent to final notice} return result; }
}
V: Two ways to delegate AOP in spring (Java dynamic Proxy and Cglib proxy)
Spring AOP uses dynamic proxy technology to weave enhanced code at runtime. Two proxy mechanisms are used: a dynamic proxy based on JDK (the JDK itself provides only proxies for interfaces), and a dynamic proxy based on Cglib.
1. The dynamic proxy for JDK mainly involves two classes in the Java.lang.reflect package: Proxy and Invocationhandler. Where Invocationhandler is just an interface, you can define the crosscutting logic by implementing the interface, and call the target class's code through the reflection mechanism, and dynamically weave the crosscutting logic together with the business logic. Proxy uses Invocationhandler to create an instance of an interface to generate the proxy object of the target class. (only proxy instances can be created for interfaces)
The interface that needs to be represented is public interface Forumservice {public void removetopic (int topicid);
public void Removeforum (int forumid); The implementation class of the proxy interface, containing the core business logic public class Forumserviceimpl implements forumservice{@Override the public void removetopic (int to
PICID) {System.out.println ("Simulate delete topic record:" + topicid);
try {thread.currentthread (). Sleep (20);
catch (Interruptedexception e) {e.printstacktrace ();
} @Override public void removeforum (int forumid) {System.out.println ("Simulate Delete forum record:" + ForumID);
try {thread.currentthread (). Sleep (40);
catch (Interruptedexception e) {e.printstacktrace ();
The performance monitoring core code generates public class Methodperformance {private long begin;
private long end;
Private String Servicemethod;
Public methodperformance (String servicemethod) {this.servicemethod = Servicemethod;
This.begin = System.currenttimemillis ();
};
public void Printperformance () {this.end = System.currenttimemillis ();
Long elapse = This.end-this.begin; SYstem.out.println (Servicemethod + "cost" + elapse + "MS"); }//thread-Safe crosscutting logic public class PerformanceMonitor {private static threadlocal<methodperformance> tl= new Threadloca
L<methodperformance> ();
public static void Begin (String method) {System.out.println ("begin Monitor");
Methodperformance MP = new Methodperformance (method);
Tl.set (MP);
public static void End () {System.out.println (' End Monitor ');
Methodperformance MP = Tl.get ();
Mp.printperformance ();
}//AOP the crosscutting module public class Perfermancehandler implements invocationhandler{private Object target;
Public Perfermancehandler (Object target) {this.target = target; @Override public Object Invoke (object Proxy, Method method, object[] args) throws Throwable {PerformanceMonitor . Begin (Target.getclass (). GetName () + "."
+method.getname ());
Object = Method.invoke (target, args);
Performancemonitor.end ();
return object; }//Test public class Testforumservice {public static VOID Main (string[] args) {forumservice target = new Forumserviceimpl ();
Weave the target business class with the crosscutting code perfermancehandler handler = new Perfermancehandler (target); Create Proxy instance Forumservice proxy = (forumservice) proxy.newproxyinstance (Target.getclass (). getClassLoader (), TA
Rget.getclass (). Getinterfaces (), handler);
Proxy.removeforum (10);
Proxy.removetopic (1012); }
}
Begin Monitor
Analog Delete Forum Record: 10
End Monitor
Com.baobaotao.proxy.ForumServiceImpl.removeForum cost 42ms
Begin Monitor
Analog Delete topic record: 1012
End Monitor
Com.baobaotao.proxy.ForumServiceImpl.removeTopic cost 21ms
2.CGLib uses the underlying bytecode technology to create subclasses for a class, and in subclasses, methods to intercept the invocation methods of all the parent classes, and to weave the crosscutting logic.
Package com.baobaotao.proxy;
Import Java.lang.reflect.Method;
Import Org.springframework.cglib.proxy.Enhancer;
Import Org.springframework.cglib.proxy.MethodInterceptor;
Import Org.springframework.cglib.proxy.MethodProxy;
public class Cglibproxy implements methodinterceptor{private enhancer enhancer = new enhancer ();
Public Object GetProxy (class Clazz) {Enhancer.setsuperclass (clazz);//Set Class Enhancer.setcallback (this) to create subclasses; return enhancer.create ()//The subclass instance is dynamically created by bytecode technology @Override public object intercept (object target, methods method, object[] args, Methodproxy proxy) throws Throwable {Performancemonitor.begin (Target.getclass (). GetName () + "."
+method.getname ());
Object = Proxy.invokesuper (target, args);
Performancemonitor.end ();
return object;
}} package Com.baobaotao.proxy;
Import Java.lang.reflect.Proxy; Test public class Testforumservice {public static void main (string[] args) {cglibproxy cglibproxy = new Cglibproxy ()
; Forumserviceimpl Service = (Forumserviceimpl) cglibproxy.getproxy (Forumserviceimpl.class);
Service.removeforum (10);
Service.removetopic (1012); }
}
Begin Monitor
Analog Delete Forum Record: 10
End Monitor
com.baobaotao.proxy.forumserviceimpl$ $EnhancerByCGLIB $$626e31f5 (subclass). Removeforum Cost 67ms
Begin Monitor
Analog Delete topic record: 1012
End Monitor
com.baobaotao.proxy.forumserviceimpl$ $EnhancerByCGLIB $$626e31f5.removetopic Cost 20ms
Spring Enhancement class
Spring supports 5 types of enhancements:
1 predecessor Enhancements: Org.springframework.aop.BeforeAdvice represents predecessor enhancements, spring only supports method-level enhancements, and Methodbeforeadvice is currently available.
Public interface Waiter {public void Greetto (String name);
public void Serveto (String name); The public class Naivewaiter implements waiter {@Override public void Greetto (String name) {System.out.println ("greet
To "+ name +" ... ");
@Override public void Serveto (String name) {System.out.println ("Serveto" + name + "...");
}} import Java.lang.reflect.Method;
Import Org.springframework.aop.MethodBeforeAdvice; The public class Greetebeforeadvice implements methodbeforeadvice{@Override the public void before (method arg0, object[] arg1,
Object arg2) throws Throwable {string client = (string) arg1[0]; System.out.println ("How are you!")
+client+ ".");}
Import Org.springframework.aop.BeforeAdvice;
Import Org.springframework.aop.framework.ProxyFactory;
public class Testbeforeadvice {public static void main (string[] args) {Waiter target = new Naivewaiter ();
Beforeadvice advice = new Greetebeforeadvice (); Spring provides agent factory proxyfactory pf = new Proxyfactory ()//UseCglib2aopprox is Cglib Agent technology create agent//Pf.setinterfaces (Target.getclass (). Getinterfaces ());//Use Jdkdynamicaopproxy//
Set agent target Pf.settarget (target);
Add enhanced processing pf.addadvice (advice);
Generate proxy instance Waiter waiter = (waiter) pf.getproxy ();
Waiter.greetto ("Tom");
Waiter.serveto ("Lucy");
ApplicationContext CTX = new Classpathxmlapplicationcontext ("Beans.xml");
Waiter Waiter1 = (waiter) Ctx.getbean ("Waiter");
Waiter1.greetto ("John"); } <bean id= "target" class= "Com.baobaotao.advice.NaiveWaiter"/> <bean id= "Greeteadvice" Com.baobaotao.advice.GreeteBeforeAdvice "/> <bean id=" Waiter "class=" Org.springframework.aop.framework.ProxyFactoryBean "p:proxyinterfaces=" Com.baobaotao.advice.Waiter "P: Interceptornames= "Greeteadvice" p:target-ref= "target"/>
2 post enhancement: Org.springframework.aop.AfterReturningAdvice represents post enhancement and is enforced after the target method is implemented.
Import Java.lang.reflect.Method;
Import Org.springframework.aop.AfterReturningAdvice;
The public class Greeteafteradvice implements afterreturningadvice{@Override the public
void afterreturning (Object Arg0, Method Arg1, object[] arg2,
Object arg3) throws Throwable {System.out.println
("please enjoy yourself!");
}
}
<bean id= "Waiter" class= "Org.springframework.aop.framework.ProxyFactoryBean"
Com.baobaotao.advice.Waiter "p:interceptornames=" Greetebefore,greeteafter "
p:target-ref=" target "/>
3 Surround Enhancement: Org.aopalliance.intercept.MethodInterceptor represents surround enhancement, which is enforced before and after the target method executes.
Import Org.aopalliance.intercept.MethodInterceptor;
Import org.aopalliance.intercept.MethodInvocation;
The public class Greeteinterceptor implements methodinterceptor{@Override the public
Object Invoke (methodinvocation INV) throws Throwable {
object[] args = Inv.getarguments ();
String client = (string) args[0];
System.out.println ("How are you!") +client+ ".");
Object obj = Inv.proceed ();
SYSTEM.OUT.PRINTLN ("Please enjoy yourself!");
return obj;
}
}
4 exception throwing Enhancement: Org.springframework.aop.ThrowsAdvice, enforcing after the target method throws an exception. The method name must be afterthrowing, such as the first three optional arguments, and the last one is Throwable or its subclasses.
Import Java.lang.reflect.Method;
Import Org.springframework.aop.ThrowsAdvice;
public class TransactionManager implements Throwsadvice {public
void Afterthrowing (Method method, object[] args, OBJ ECT target,
Exception ex) throws Throwable {
System.out.println ("-----------");
System.out.println ("Method:" + method.getname ());
System.out.println ("Throw exception:" + Ex.getmessage ());
SYSTEM.OUT.PRINTLN ("The transaction was successfully rolled back.") ");
}
}
5 Introduction Enhancement: Org.springframework.aop.IntroductionInterceptor, indicates that the target class adds new methods and properties, and the connection point is a class level, not a method level.
Import org.aopalliance.intercept.MethodInvocation;
Import Org.springframework.aop.support.DelegatingIntroductionInterceptor;
Import Com.baobaotao.proxy.PerformanceMonitor; public class Controllableperformacemonitor extends Delegatingintroductioninterceptor implements monitorable{private
threadlocal<boolean> Monitorstatusmap = new threadlocal<boolean> ();
@Override public void Setmonitoractive (Boolean active) {Monitorstatusmap.set (active);
@Override public Object Invoke (Methodinvocation mi) throws throwable {Object obj = null; if (monitorstatusmap.get ()!= null && monitorstatusmap.get ()) {Performancemonitor.begin mi.getclass ().
GetName () + "."
+ Mi.getmethod (). GetName ());
obj = Super.invoke (mi);
Performancemonitor.end ();
else {obj = Super.invoke (mi);
return obj; } <bean id= "Forumservice" class= Org.springframework.aop.framework.ProxyFactoryBean "p:interfaces="
Com.baobaotao.introduce.Monitorable "//Introducing an introduction to enhance the interface to be implementedp:target-ref= "Forumservicetarget" p:interceptornames= "Pmonitor" p:proxytargetclass= "true"/>// Enhanced proxies can only be generated by creating subclasses for the target type class
How AOP slices are configured
1 Schema-based configuration: Describes pointcuts, enhanced types in XML, and slice classes for Pojo
2 Based on ASPECTJ configuration: pointcuts, enhanced types using annotations to describe