Spring AOP之高级应用--在已有的bean中引入行为

问题:

有时候有一组共享公共行为类。在OOP中,它们必须扩展相同的基类或者实现相同的接口。

此外,Java的单继承机制仅允许一个类最多扩展一个基类。所以,不能同时从多个实现类中继承行为。

解决方案:

引入是AOP中的一种特殊的通知。它允许为一个接口提供实现类,使对象动态的实现接口。就像对象在运行时扩展了实现类。而且,可以用多个实现类将多个接口同时引入对象。这可以实现与多重继承相同的效果。

实例:

假设有两个接口MaxCalculator与MinCalculator,其代码如下:

public interface MinCalculator {

	double min(double a,double b);
}
public interface MaxCalculator {

	double max(double a,double b);
}
其实现类代码如下:

public class MaxCalculatorImpl implements MaxCalculator {

	@Override
	public double max(double a, double b) {
		double result = a<=b?b:a;
		System.out.println("max("+a+","+b+")="+result);
		return result;
	}

}
public class MinCalculatorImpl implements MinCalculator {

	@Override
	public double min(double a, double b) {
		double result = a<=b?a:b;
		System.out.println("min("+a+","+b+")="+result);
		return result;
	}

}
而又另外一个类 ArithmeticCalculatorImpl希望也执行min()与max()计算。因为java语言仅支持单继承,让 ArithmeticCalculatorImpl同时扩展MaxCalculatorImpl与MinCalculatorImpl是不可能的。唯一的方法通过复制实现代码或者将处理委派给实际的实现类,扩展某个类(MaxCalculatorImpl)并实现另一个接口(MaxCalculator)。

ArithmeticCalculatorImpl代码:

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;
    }
}

使用引入,可以使用实现类MaxCalculatorImpl与MinCalculatorImpl动态的实现MaxCalculator与MinCalculator接口。这和从MaxCalculatorImpl与MinCalculatorImpl多重继承有相同的效果。引入可以不需要修改ArithmeticCalculatorImpl类引入新的方法。即,可在没有源代码的情况下将方法引入到现有的类中。

Spring AOP之所以能够使用引入,即使用了动态代理。引入就是向动态代理添加一个接口(MaxCalculator),当这个接口声明的方法在代理对象上调用时,代理将把调用委派给后端实现类(MaxCalculatorImpl)。

引入类代码:

@Aspect
public class CalculatorIntroduction {

	@DeclareParents(value="com.apress.springrecipes.calculator.ArithmeticCalculatorImpl",
			defaultImpl=com.apress.springrecipes.calculator.MaxCalculatorImpl.class)
	public MaxCalculator maxCalculator;
	
	@DeclareParents(value="com.apress.springrecipes.calculator.ArithmeticCalculatorImpl",
			defaultImpl=MinCalculatorImpl.class)
	public MinCalculator minCalculator;
}
spring配置文件:

<?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:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.1.xsd
        http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    <context:annotation-config/>
	<aop:aspectj-autoproxy/>
	<bean class="com.apress.springrecipes.calculator.CalculatorIntroduction"></bean>
	<bean id="arithmeticCalculator"
        class="com.apress.springrecipes.calculator.ArithmeticCalculatorImpl" />

    <bean id="unitCalculator"
        class="com.apress.springrecipes.calculator.UnitCalculatorImpl" />
</beans>
调用方式:

public class IntroductionTest {
	private ApplicationContext context;
	public ApplicationContext getContext(){
		if(context==null){
			context = new  ClassPathXmlApplicationContext("xml/aop/introduction.xml");
		}
		return context;
	}
	public static void main(String[] args) {
		IntroductionTest ct = new IntroductionTest();
		ArithmeticCalculator ac = (ArithmeticCalculator)ct.getContext().getBean("arithmeticCalculator");
		
		MinCalculator min = (MinCalculator)ac;
		min.min(2.3,4.5);
		
		MaxCalculator max = (MaxCalculator)ac;
		max.max(3, 5);
	}
}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值