spring recipes读书笔记--理解AOP原理

引入一个简单的数值计算器的例子,首先创建计算器接口,然后提供一个简单的实现类,在实现类中,需要对传入参数进行验证,并且进行日志记录。

package com.aop.example;

public interface ArithmeticCalculator {
public double add(double a,double b);
public double sub(double a,double b);
}

package com.aop.example;

import com.sun.org.apache.commons.logging.Log;
import com.sun.org.apache.commons.logging.LogFactory;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

private Log log=LogFactory.getLog(this.getClass());

public double add(double a, double b) {
// TODO Auto-generated method stub
log.info("the method add() begins with "+a+","+b);
validate(a);
validate(b);
double result = a+b;
System.out.println(a+"+"+b+" = "+result);
log.info("the method add() ends with "+result);
return result;
}

public double sub(double a, double b) {
// TODO Auto-generated method stub
log.info("the method add() begins with "+a+","+b);
validate(a);
validate(b);
double result = a-b;
System.out.println(a+"-"+b+" = "+result);
log.info("the method add() ends with "+result);
return result;
}

private void validate(double a) {
// TODO Auto-generated method stub
if(a<0){
throw new IllegalArgumentException("Illegal argument");
}
}
}



上述代码中,日志和验证属于非业务需求,将这类代码写入业务逻辑中,耦合性增大,并且带来了很多的重复性代码。如果日志和验证需求改变,必须修改所有模块。
[color=red]计算器应该只关心核心计算逻辑,需要将日志和验证关注点从其中分离出来。[/color]
采用动态代理的方法,建立InvocationHandler接口,并提供日志和验证实现类。

package com.aop.example;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator {

public double add(double a, double b) {
// TODO Auto-generated method stub
double result = a+b;
System.out.println(a+"+"+b+" = "+result);
return result;
}

public double sub(double a, double b) {
// TODO Auto-generated method stub
double result = a-b;
System.out.println(a+"-"+b+" = "+result);
return result;
}
}

package com.aop.example;

import java.lang.reflect.Method;

public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}

package com.aop.example;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

import com.sun.org.apache.commons.logging.Log;
import com.sun.org.apache.commons.logging.LogFactory;

public class CalculatorLoggingHandler implements InvocationHandler {

private Log log = LogFactory.getLog(this.getClass());

private Object target;

public CalculatorLoggingHandler(Object target) {
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
log.info("the method "+ method.getName()+" begins with "+Arrays.toString(args));
Object result=method.invoke(target, args);
log.info("the method "+method.getName()+" ends with "+result);
return result;
}

public static Object createProxy(Object target){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new CalculatorLoggingHandler(target));
}
}

package com.aop.example;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CalculatorValidationHandler implements InvocationHandler {

private Object target;

public CalculatorValidationHandler(Object target) {
super();
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
for(Object arg:args){
validate((Double)arg);
}
Object result = method.invoke(target, args);
return result;
}

private void validate(double a){
if(a<0){
throw new IllegalArgumentException("illegal argument");
}
}
public static Object createProxy(Object target){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new CalculatorLoggingHandler(target));
}
}



最后做一下测试

package com.aop.example;

public class AopTest {
public static void main(String[] args){
ArithmeticCalculator arithmeticCalculatorImpl= new ArithmeticCalculatorImpl();
ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) CalculatorValidationHandler.createProxy
(CalculatorLoggingHandler.createProxy(arithmeticCalculatorImpl));
arithmeticCalculator.add(1.0, 2.0);
arithmeticCalculator.add(-2.2, 2.0);
arithmeticCalculator.sub(3.0, 2.0);
}
}


这里[color=red]使用验证代理包装日志代理形成了一个代理链[/color]。所有计算器的调用首先经过验证代理,然后再是日志代理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Solve all your Spring 5 problems using complete and real-world code examples. When you start a new project, you’ll be able to copy the code and configuration files from this book, and then modify them for your needs. This can save you a great deal of work over creating a project from scratch. The recipes in Spring 5 Recipes cover Spring fundamentals such as Spring IoC container, Spring AOP/ AspectJ, and more. Other recipes include Spring enterprise solutions for topics such as Spring Java EE integration, Spring Integration, Spring Batch, Spring Remoting, messaging, transactions, and working with big data and the cloud using Hadoop and MongoDB. Finally, Spring web recipes cover Spring MVC, other dynamic scripting, integration with the popular Grails Framework (and Groovy), REST/web services, and more. You’ll also see recipes on new topics such as Spring Framework 5, reactive Spring, Spring 5 microservices, the functional web framework and much more. This book builds upon the best-selling success of the previous editions and focuses on the latest Spring Framework features for building enterprise Java applications. What You'll Learn Get re-usable code recipes and snippets for core Spring, annotations and other development tools Access Spring MVC for web development Work with Spring REST and microservices for web services development and integration into your enterprise Java applications Use Spring Batch, NoSQL and big data for building and integrating various cloud computing services and resources Integrate Java Enterprise Edition and other Java APIs for use in Spring Use Grails code and much more Who This Book Is For Experienced Java and Spring programmers.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值