AOP defines a group of high-level concepts for application developers to express their crosscutting concerns. First, the crosscutting action to take at a particular execution point is encapsulated in an advice. For example, you can encapsulate the logging and validation actions in one or more advices.
Classic Spring AOP supports four types of advices, each of which takes effect at different times of an execution point. In the formal AOP definition, there are many types of execution points, including method executions, constructor executions, and field accesses. However, Spring AOP only supports method executions. So, the definition of the four classic advice types can be narrowed down to the following:
- Before advice: Before the method execution
- After returning advice: After the method returns a result
- After throwing advice: After the method throws an exception
- Around advice: Around the method execution
How it works?,now let's seeing a simple example:
first,define two interfaces:
package cn.cgw.aop;
public interface ArithmeticCalculator {
public double add(double a, double b);
public double sub(double a, double b);
public double mul(double a, double b);
public double div(double a, double b);
}
package cn.cgw.aop;
public interface UnitCalculator {
public double kilogramToPound(double kilogram);
public double kilometerToMile(double kilometer);
}
and then,we implement them:
package cn.cgw.aop;
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
public double add(double a, double b) {
double result = a + b;
System.out.println(a + " + " + b + " = " + result);
return result;
}
public double sub(double a, double b) {
double result = a - b;
System.out.println(a + " - " + b + " = " + result);
return result;
}
public double mul(double a, double b) {
double result = a * b;
System.out.println(a + " * " + b + " = " + result);
return result;
}
public double div(double a, double b) {
if (b == 0) {
throw new IllegalArgumentException("Division by zero");
}
double result = a / b;
System.out.println(a + " / " + b + " = " + result);
return result;
}
}
package cn.cgw.aop;
public class UnitCalculatorImpl implements UnitCalculator {
public double kilogramToPound(double kilogram) {
double pound = kilogram * 2.2;
System.out.println(kilogram + " kilogram = " + pound + " pound");
return pound;
}
public double kilometerToMile(double kilometer) {
double mile = kilometer * 0.62;
System.out.println(kilometer + " kilometer = " + mile + " mile");
return mile;
}
}
now,we define 4 instance for erery advice:
before advice:
public class LoggingBeforeAdvice implements MethodBeforeAdvice {
private Log log = LogFactory.getLog(this.getClass());
public void before(Method method, Object[] args, Object target)
throws Throwable {
log.info("The method:" + method.getName() + "()begin with" + Arrays.toString(args));
}
}
After returning advice:
public class LoggingAfterAdvice implements AfterReturningAdvice {
private Log log = LogFactory.getLog(this.getClass());
public void afterReturning(Object returnValue, Method method, Object[] args,
Object target) throws Throwable {
log.info("The method:" + method.getName() + "() end with " + returnValue);
}
}
After throwing advice:
public class LoggingThrowsAdvice implements ThrowsAdvice {
private Log log = LogFactory.getLog(this.getClass());
public void afterThrowing(Method method, Object[] args, Object target,
IllegalArgumentException e) throws Throwable {
log.error("Illegal argument " + Arrays.toString(args) + " for method "
+ method.getName() + "()");
}
}
Around advice:
public class LoggingAroundAdvice implements MethodInterceptor {
private Log log = LogFactory.getLog(this.getClass());
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
log.info("The method " + methodInvocation.getMethod().getName()
+ "() begins with "
+ Arrays.toString(methodInvocation.getArguments()));
try {
Object result = methodInvocation.proceed();
log.info("The method " + methodInvocation.getMethod().getName()
+ "() ends with " + result);
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument "
+ Arrays.toString(methodInvocation.getArguments())
+ " for method " + methodInvocation.getMethod().getName()
+ "()");
throw e;
}
}
}
configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="arithmeticCalculator" class="cn.cgw.aop.ArithmeticCalculatorImpl"/>
<bean id="unitCalculator" class="cn.cgw.aop.UnitCalculatorImpl"/>
<!-- Advice -->
<bean id="loggingBeforeAdvice" class="cn.cgw.aop.LoggingBeforeAdvice"/>
<bean id="loggingAfterAdvice" class="cn.cgw.aop.LoggingAfterAdvice"/>
<bean id="loggingThrowsAdvice" class="cn.cgw.aop.LoggingThrowsAdvice"/>
<bean id="loggingAroundAdvice" class="cn.cgw.aop.LoggingAroundAdvice"/>
<!-- AOP Proxy -->
<bean id="arithmeticCalculatorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>cn.cgw.aop.ArithmeticCalculator</value>
</list>
</property>
<property name="target" ref="arithmeticCalculator"/>
<property name="interceptorNames">
<list>
<value>loggingBeforeAdvice</value>
<value>loggingAfterAdvice</value>
<value>loggingThrowsAdvice</value>
<!--
<value>loggingAroundAdvice</value>
-->
</list>
</property>
</bean>
<bean id="unitCalculatorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>cn.cgw.aop.UnitCalculator</value>
</list>
</property>
<property name="target" ref="unitCalculator"/>
<property name="interceptorNames">
<list>
<value>loggingBeforeAdvice</value>
<value>loggingAfterAdvice</value>
<!--
<value>loggingAroundAdvice</value>
-->
</list>
</property>
</bean>
</beans>
finally,we write a test method:
ApplicationContext context = new ClassPathXmlApplicationContext("beans-aop.xml");
ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator)context.getBean("arithmeticCalculatorProxy");
UnitCalculator unitCalculator = (UnitCalculator)context.getBean("unitCalculatorProxy");
arithmeticCalculator.add(1, 2);
arithmeticCalculator.sub(4, 3);
arithmeticCalculator.mul(2, 3);
arithmeticCalculator.div(4, 0);
unitCalculator.kilogramToPound(10);
unitCalculator.kilometerToMile(5);
分享到:
相关推荐
Chapter 7, Separating Concerns with Typed Services, discusses how it’s bad practice to allow our logic to live in our components. In such a case, Angular allows you to provide API methods via ...
Core concerns that cut across all parts of your application, such as logging or authorization, are difficult to maintain independently. In aspect-oriented programming (AOP) you isolate these cross-...
Chapter 12: Modularizing Your Code and Publishing Node.js Modules to npm Chapter 13: Node HTTP/2 Servers Chapter 14: Asynchronous Code in Node Chapter 15: Node Microservices with Docker and AWS ECS ...
1.5.2 Comparing Python with Other Languages 11 1.5.3 How Is It Used? 14 1.5.4 Who Uses Python? 15 1.5.5 Flavors of Python 15 1.5.6 Special Python Distributions 16 1.6 ADDITIONAL RESOURCES 17 Chapter 2...
#### Chapter 9: Modularizing an Application Modularization is crucial for maintaining large-scale applications. This chapter covers the use of the GWT module's XML configuration file to manage ...
It also offers aspects-oriented programming (AOP) support for modularizing cross-cutting concerns. SpringMVC, as the presentation layer, handles HTTP requests and responses, ensuring a clean ...
As a developer, you may inherit projects built on existing codebases with design patterns, usage assumptions, infrastructure, and tooling from another time and another team. Fortunately, there are ...
with the particular requirements and challenges from the design of Android’s software stack.ASFprovides a novel security API that supports authors of Android security extensions in developing their ...
The book's many examples concentrate on modularizing non-functional requirements that often sprawl throughout object-oriented projects. You'll appreciate its straightforward introduction using ...
Core topics include deciphering and modularizing awkward code structures, effectively integrating and automating tests, replacing an outdated build system, and infrastructure automation using tools ...
3 Computing with Numbers 25 3.1 Numeric Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.2 Using the Math Library . . . . . . . . . . . . . . . . . . . . . ....
- **eCATT Part 4 - Modularizing Script**:介绍如何将复杂的脚本分解成多个模块。 - **eCATT Part 5 - Conditional Execution**:解释如何根据条件来控制脚本的执行流程。 - **eCATT Part 6 - System Data ...