Spring AOP @Aspect J:我如何让Aspects访问其他类

时间:2015-04-09 13:17:58

标签: class aspectj spring-aop aop

我是Java和Spring的新手。我想知道是否有可能,如果是这样的话,我怎样才能将我的方面应用于多个课程,而不必从课程中调用方法" work"。

这是我的主要课程。 Aspects可以处理我从这个类中直接调用的任何方法,但不会对其他类调用的任何其他方法起作用(即使它们不是内部的)

public class AopMain {
    public static void main(String[] args) {
        String selection = "on";
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");  

        do {
            try{
                System.out.println("Enter 'length' for a length conversion and 'temperature' for a temperature conversion and 'quit' to quit");
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                selection = br.readLine();
                if(selection.contentEquals("length")) {
                    LengthService lengthService = ctx.getBean("lengthService", LengthService.class);
                    lengthService.runLengthService();
                    lengthService.display();
                }
                else if(selection.contentEquals("temperature")) {
                    TemperatureService temperatureService = new TemperatureService();
                    temperatureService.runTempertureService();
                    temperatureService.display();
                }
            }
            catch (Exception e) {
                System.out.println("Input error");
            }
        } while (!selection.contentEquals("quit"));
    }
}

这是转换服务类之一:

public class TemperatureService {
    String fromUnit = null;
    String toUnit = null;
    double val = 0;
    double converted = 0;

    public void runTempertureService() {
        Scanner in = new Scanner(System.in);

        System.out.println("Convert from (enter C, K, F): ");
        fromUnit = in.nextLine();
        System.out.println("Convert to (enter C, K, F): "); 
        toUnit = in.nextLine();

        TemperatureConverter from = new TemperatureConverter(fromUnit);
        TemperatureConverter to = new TemperatureConverter(toUnit);

        System.out.println("Value:");
        val = in.nextDouble(); 

        double celcius = from.toCelcius(val);
        converted = to.fromCelcius(celcius);
        from.display(val, fromUnit, converted, toUnit);

        System.out.println(val + " " + fromUnit + " = " + converted + " " + toUnit);
    }

    public String[] display(){
        String[] displayString = {Double.toString(val), fromUnit, Double.toString(converted), toUnit};
        return displayString;
    }
}

这是转换类之一:

public class TemperatureConverter {
    final double C_TO_F = 33.8;
    final double C_TO_C = 1;
    final double C_TO_KELVIN = 274.15;

    private double factor;

    public TemperatureConverter(String unit) {
        if (unit.contentEquals("F"))
            factor = C_TO_F;
        else if(unit.contentEquals("C"))
            factor = C_TO_C;
        else if(unit.contentEquals("K"))
            factor = C_TO_KELVIN;
    }

    public double toCelcius(double measurement) {
        return measurement * factor; 
    }

    public double fromCelcius(double measurement) {
        return measurement/factor;
    }

    public TemperatureConverter() {}
    public void display(double val, String fromUnit, double converted, String toUnit) {}
}

这是我的配置文件:

<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <aop:aspectj-autoproxy/>

    <bean name= "lengthConverter" class= "converter.method.LengthConverter"/>   
    <bean name= "temperatureConverter" class= "converter.method.TemperatureConverter"/>
    <bean name= "lengthService" class= "converter.service.LengthService" autowire = "byName"/>
    <bean name= "temperatureService" class= "converter.service.TemperatureService"/>
    <bean name="ValidationAspect" class= "converter.aspect.ValidationAspect" />
    <bean name="DisplayAspect" class= "converter.aspect.DisplayAspect" />
</beans>

我希望能够将一个方面应用于服务类调用的转换器类的函数,但是就像我刚才提到的那样,它无法直接从主类调用该方法。 (显示功能最初是转换器类的一部分,但我移动它以便方面可以工作)。另外为什么方面不会接受newline()方法调用?

修改

这是我的一个方面:

@Aspect
public class DisplayAspect {
     @AfterReturning(pointcut = "execution(* display(..))", returning = "retVal")
     public void fileSetUp(Object retVal) {
        System.out.println("So we found the display things");
        Writer writer = null;
        String[] returnArray = (String[]) retVal;

        try {
            System.out.println("inside try");
            String text = "The opertion performed was: " + returnArray[0] + " in " + returnArray[1] + " is " + returnArray[2] + " " + returnArray[3] + "\n";
            File file = new File("Log.txt");
            writer = new BufferedWriter(new FileWriter(file, true));
            writer.write(text);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     }
}

1 个答案:

答案 0 :(得分:0)

  

我希望能够将一个方面应用于转换器类的功能

好吧,然后更改你的切入点,以便拦截你想要在你的建议中处理的方法(不是函数,它们被称为方法)。目前切入点是

execution(* display(..))

即。它将使用任意数量的参数和任何返回类型拦截名为display的所有方法。如果您想要拦截所有转换器方法,请将其更改为

execution(* converter.method.TemperatureConverter.*(..))

代替。

  像我刚才提到的那样,它无法直接从主类调用方法。

我需要猜测,因为这个描述不清楚,但可能你要描述的是,只有在从类外部调用TemperatureService.display()而不是从{{1 }}。这是Spring AOP的一个已知且描述良好的限制,请参阅Spring Manual, chapter 9.6, "Proxying mechanisms":由于Spring AOP的基于代理的“AOP lite”方法,这是行不通的,因为对TemperatureService方法的内部调用是不通过Spring容器创建的动态代理路由。因此,Spring AOP仅适用于bean之间的调用,而不适用于bean内调用。如果您需要拦截内部调用,则需要切换到完整的AspectJ,它可以通过LTW(加载时编织)轻松集成到Spring应用程序中,如chapter 9.8, "Using AspectJ with Spring applications"中所述。