In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article will explain in detail how to analyze the application of AOP. The content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.
AOP (Aspect-Oriented Programming, aspect-oriented programming) is a technology that can add functions to a program dynamically and uniformly without modifying the source code through pre-compilation and runtime dynamic proxy. It is a new methodology and a supplement to traditional OOP programming.
OOP is concerned with dividing the requirements function into different and relatively independent, well-packaged classes, and let them have their own behavior, relying on inheritance and polymorphism to define the relationship between each other; AOP hopes to be able to separate the common requirements function from the unrelated classes, so that many classes can share a behavior, once a change occurs, there is no need to modify many classes, but only need to modify the behavior.
AOP modularizes crosscutting concerns using aspect, and OOP modularizes state and behavior using classes. In the world of OOP, programs are organized by classes and interfaces, so it is appropriate to use them to implement the core business logic of the program. However, it is very difficult to implement crosscutting concerns (functional requirements that span multiple modules of the application), such as logging and verification.
/ * Calculator Interface * / public interface Calculator {public double add (double num1, double num2) throws Exception; public double sub (double num1, double num2) throws Exception; public double div (double num1, double num2) throws Exception; public double mul (double num1, double num2) throws Exception } / * implementation class of calculator interface * / public class ArithmeticCalculator implements Calculator {@ Override public double add (double num1, double num2) {double result = num1 + num2; return result;} @ Override public double sub (double num1, double num2) {double result = num1-num2; return result } / * the hint code does not consider the divisor 0 for the time being * / @ Override public double div (double num1, double num2) {double result = num1 / num2; return result;} @ Override public double mul (double num1, double num2) {double result = num1 * num2; return result;}}
Most applications have a common requirement to track what is happening while the program is running. To add logging to the computer, the ArithmeticCalculator class changes as follows:
/ * implementation class of calculator interface, add logging function * / public class ArithmeticCalculator implements Calculator {@ Override public double add (double num1, double num2) {System.out.println ("the method [add ()]" + "begin with args (" + num1+ "," + num2+ ")"); double result = num1+ num2; System.out.println ("the method [add ()]" + "end with result (" + result+ ")") Return result;} @ Override public double sub (double num1, double num2) {System.out.println ("the method [sub ()]" + "begin with args (" + num1+ "," + num2+ ")); double result = num1-num2; System.out.println (" the method [sub ()] "+" end with result ("+ result+") ") Return result;} / * the hint code temporarily ignores the case of divisor 0 * / @ Override public double div (double num1, double num2) {System.out.println ("the method [div ()]" + "begin with args (" + num1+ "," + num2+ ")"); double result = num1 / num2 System.out.println ("the method [div ()]" + "end with result (" + result+ ")); return result;} @ Override public double mul (double num1, double num2) {System.out.println (" the method [mul ()] "+" begin with args ("+ num1+", "+ num2+") "); double result = num1 * num2 System.out.println ("the method [mul ()]" + "end with result (" + result+ ")"); return result;}}
If ArithmeticCalculator stipulates that only positive numbers can be calculated, you need to add a parameter verification method:
/ * implementation class of calculator interface, add logging function * / public class ArithmeticCalculator implements Calculator {@ Override public double add (double num1, double num2) throws Exception {this.argsValidatior (num1); this.argsValidatior (num2) / * Ibid. * /} @ Override public double sub (double num1, double num2) throws Exception {this.argsValidatior (num1); this.argsValidatior (num2) / * Ibid * /} / * the hint code does not consider the divisor 0 for the time being * / @ Override public double div (double num1, double num2) throws Exception {this.argsValidatior (num1); this.argsValidatior (num2) / * Ibid. * /} @ Override public double mul (double num1, double num2) throws Exception {this.argsValidatior (num1); this.argsValidatior (num2); / * Ibid * /} private void argsValidatior (double arg) throws Exception {if (arg)
< 0) throw new Exception("参数不能为负数"); } } 上面的程序一个很直观的特点就是,好多重复的代码,并且当加入越来越多的非业务需求(例如日志记录和参数验证),原有的计算器方法变得膨胀冗长。这里有一件非常痛苦的事情,无法使用原有的编程方式将他们模块化,从核心业务中提取出来。例如日志记录和参数验证,AOP里将他们称为横切关注点(crosscutting concern),它们属于系统范围的需求通常需要跨越多个模块。 在使用传统的面向对象的编程方式无法理想化的模块化横切关注点,程序员不能不做的就是将这些横切关注点放置在每一个模块里与核心逻辑交织在一起,这将会导致横切关注点在每一个模块里到处存在。使用非模块化的手段实现横切关注将会导致,代码混乱,代码分散,代码重复。你想想看如果日志记录需要换一种显示方式,那你要改多少代码,一旦漏掉一处(概率很高),将会导致日志记录不一致。这样的代码很维护。种种原因表明,模块只需要关注自己原本的功能需求,需要一种方式来将横切关注点冲模块中提取出来。 忍无可忍的大牛们提出了AOP,它是一个概念,一个规范,本身并没有设定具体语言的实现,也正是这个特性让它变的非常流行,现在已经有许多开源的AOP实现框架了。本次不是介绍这些框架的,我们将不使用这些框架,而是使用底层编码的方式实现最基本的AOP解决上面例子出现的问题。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。AOP可以使用"代理模式"来实现。The principle of the proxy pattern is to wrap the object with a proxy and then replace the original object with the proxy object. Any call to the original object must first go through the proxy. The proxy object is responsible for determining whether and when to forward method call information to the original object. At the same time, the proxy object can perform some extra work around each method call. You can see that the proxy pattern is very suitable for implementing crosscutting concerns.
Since I only know Java, I think that there are two ways to implement the agent mode, one is static proxy, the other is dynamic proxy. The difference between them is whether they know who the proxy object is at compile time. In systems with many modules, static agents are not suitable and very inefficient, because static agents need to design a proxy class for each interface, and it is normal for the system to have hundreds of interfaces. Static proxy mode consumes too much manpower. Dynamic proxy is a proxy pattern supported by JDK, which can realize crosscutting concerns very well.
/ * to use a dynamic proxy, you need to implement the InvocationHandler interface * / public class ArithmeticCalculatorInvocationHandler implements InvocationHandler {/ * the object to be proxied. The dynamic proxy only knows who the agent is at run time, so it is defined as an Object type and can proxy any object * / private Object target = null; / * pass in the original object through the constructor * / public ArithmeticCalculatorInvocationHandler (Object target) {this.target = target } / * the method of the InvocationHandler interface, proxy represents the proxy, and method represents the method that the original object is called Args represents the parameter of the method * / @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {/ * processing log information before calling the original object method * / System.out.println ("the method [" + method.getName () + "]" + "begin with args (" + Arrays.toString (args) + ")")) Object result = method.invoke (this.target, args); / * processing log information after the original object method call * / System.out.println ("the method [" + method.getName () + "]" + "end with result (" + result+ ")"); return result } / * get proxy class * / public Object getProxy () {return Proxy.newProxyInstance (this.target.getClass (). GetClassLoader (), this.getClass (). GetInterfaces (), this);}}
The scenario class calls:
Public class Client {public static void main (String [] args) throws Exception {/ * get proxy * / Calculator arithmeticCalculatorProxy = (Calculator) new ArithmeticCalculatorInvocationHandler (new ArithmeticCalculator ()) .getProxy (); / * call add method * / arithmeticCalculatorProxy.add (10,10);}}
Output of the console:
The method [add] begin with args ([10.0,10.0]) the method [add] end with result
You can see that crosscutting concerns are implemented using dynamic proxies.
If you need to add a parameter verification feature, you only need to create another parameter verification agent:
Public class ArithmeticCalculatorArgsInvocationHandler implements InvocationHandler {/ * for the object to be proxied, the dynamic proxy only knows who to proxy at run time, so it is defined as Object type, and can proxy any object * / private Object target = null; / * pass the original object * / public ArithmeticCalculatorArgsInvocationHandler (Object target) {this.target = target through the constructor } / * method of the InvocationHandler interface, proxy represents the proxy, method represents the method called by the original object, and args represents the parameter of the method * / @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {System.out.println ("begin valid method [" + method.getName () + "] with args" + Arrays.toString (args) For (Object arg: args) {this.argValidtor ((Double) arg);} Object result = method.invoke (this.target, args); return result } / * get proxy class * / public Object getProxy () {return Proxy.newProxyInstance (this.target.getClass (). GetClassLoader (), this.target.getClass (). GetInterfaces (), this);} private void argValidtor (double arg) throws Exception {if (arg < 0) throw new Exception ("argument cannot be negative!") ;}}
The scenario class calls:
Public class Client {public static void main (String [] args) throws Exception {/ * get the agent * / Calculator arithmeticCalculatorProxy = (Calculator) new ArithmeticCalculatorInvocationHandler (new ArithmeticCalculator ()). GetProxy (); Calculator argValidatorProxy = (Calculator) new ArithmeticCalculatorArgsInvocationHandler (arithmeticCalculatorProxy). GetProxy (); / * call add method * / argValidatorProxy.add (10,10);}}
Console output:
Begin valid method [add] with args [10.0,10.0] the method [add] begin with args ([10.0,10.0]) the method [add] end with result
Enter a negative number:
Public class Client {public static void main (String [] args) throws Exception {/ * get the agent * / Calculator arithmeticCalculatorProxy = (Calculator) new ArithmeticCalculatorInvocationHandler (new ArithmeticCalculator ()). GetProxy (); Calculator argValidatorProxy = (Calculator) new ArithmeticCalculatorArgsInvocationHandler (arithmeticCalculatorProxy). GetProxy (); / * call add method * / argValidatorProxy.add (- 10,10);}}
Console output:
Begin valid method [add] with args [- 10.0,10.0] Exception in thread "main" java.lang.Exception: parameter cannot be negative! At com.beliefbetrayal.aop.ArithmeticCalculatorArgsInvocationHandler.argValidtor (ArithmeticCalculatorArgsInvocationHandler.java:46) at com.beliefbetrayal.aop.ArithmeticCalculatorArgsInvocationHandler.invoke (ArithmeticCalculatorArgsInvocationHandler.java:29) at $Proxy0.add (Unknown Source) at com.beliefbetrayal.aop.Client.main (Client.java:14)
I don't know if you have ever used Struts2, this structure is very similar to Struts2's interceptor, one by one Action object is like our original object business core, one by one interceptor is like the proxy here, the general function is realized as interceptor, so that Action can be shared, Struts2 interceptor is also an excellent implementation of AOP.
About how to carry on the AOP application analysis to share here, hoped that the above content can have the certain help to everybody, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.