在Spring Framework私有方法中使用AspectJ进行加载时编织

时间:2013-06-19 08:13:21

标签: spring aspectj load-time-weaving

我已经构建了一个应用程序来测试在类周围注入日志信息(进入和退出)。我使用spring构建它并使用以下示例来构建它。

http://static.springsource.org/spring/docs/2.5.5/reference/aop.html#aop-aj-ltw

现在效果很好,但我有两个问题:

  • 在围绕方法编织日志时,不包括私有方法。在spring的xml设置中是否有一个设置允许私有方法被编织或是否有另一种方法?
  • 为了能够工作,我必须在META-INF / aop.xml中包含要编织的所有软件包。是否存在要使用的设置,以便可以为项目中创建的所有类编制日志信息,而无需将包名称添加到aop.xml。

下面我已经包含了所有使用的代码和xml。正如我所说,除了上述两个问题外,一切正常。请帮助我

app.java

package se.jpab.application;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

@Service
public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "spring.xml" });
        Client client = (Client) appContext.getBean("client");   
        Location clientLocation = (Location) appContext.getBean("location");        

//      Set all values
        clientLocation.setAdress1("Adress 1");
        clientLocation.setAdress2("Adress 2");
        clientLocation.setBox("N/A");
        clientLocation.setCity("City of Dallas");

        client.setName("John Doe");
        client.setUrl("http://www.url.com"); 
        client.setLocation(clientLocation);


 //     Print out all values        

        System.out.println(client.getName());        
        System.out.println(client.getUrl());
        System.out.println(client.getLocation().getAdress1());
        System.out.println(client.getLocation().getAdress2() + " " + client.getLocation().getCity());

    }
}

Client.java     包se.jpab.application;

import org.springframework.stereotype.Service;

@Service
public class Client {

    String name;
    String url;
    Location location;
    //Constructors
    public Client(String custName, String custUrl, Location custLocation){
        name = custName;
        url = custUrl;  
        location = custLocation;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public Client(){

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {      
        this.name = name;
        printThis(name);

    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void printThis(String inStr) {
        System.out.println("PRIVAT METOD");
        System.out.println("Inkommand sträng --> " + inStr);
    }   


}

Location.java

package se.jpab.application;

import org.springframework.stereotype.Service;

@Service
public class Location {

    String city;
    String adress1;
    String adress2;
    String box;

    //Constructors  
public Location (String city, String adress1, String adress2, String box){

    this.city = city;
    this.adress1 = adress1;
    this.adress2 = adress2;
    this.box = box; 

}
public Location (){

}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getAdress1() {
    return adress1;
}
public void setAdress1(String adress1) {
    this.adress1 = adress1;
}
public String getAdress2() {
    return adress2;
}
public void setAdress2(String adress2) {
    this.adress2 = adress2;
}
public String getBox() {
    return box;
}
public void setBox(String box) {
    this.box = box;
}   
}

aop.xml文件

    <!DOCTYPE aspectj PUBLIC
        "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver options=" -showWeaveInfo">
        <!-- only weave classes in our application-specific packages -->        
        <include within="se.jpab.application.*"/>
        <include within="se.jpab.aspect.*"/>
    </weaver>

    <aspects>
        <!-- weave in just this aspect -->        
        <aspect name="se.jpab.aspect.InjectLogg"/>
    </aspects>
</aspectj>

方面

package se.jpab.aspect;

import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class InjectLogg {

    private static final Log fallbackLogger = LogFactory.getLog(InjectLogg.class);

    @Around("execution(public * se.jpab.application..*.*(..))")
    public Object profile(ProceedingJoinPoint pjp) throws Throwable {
                Object invoker = pjp.getThis();
                Log logger;

                logger = LogFactory.getLog(getClassNameFrom(invoker.getClass()));

                // Start injecting logg messages on entering a method.
                logger.info("ENTERING: (" + pjp.getSignature().getName() + ")");
                try {
                    logger.info("ARGUMENTS: " + Arrays.toString(pjp.getArgs()) + ")");
                } catch (NullPointerException e) {
                    logger.info("ARGUMENTS: No arguments");
                }

                try {
                    // proceed to original method call
                    Object result = pjp.proceed();

                    // Injecting exiting messages after method is finished
                    logger.info("RESULT: " + result);
                    logger.info("EXITING: (" + pjp.getSignature().getName() + ")");

                    // Return the result of the method we are logging
                    return result;

                } catch (IllegalArgumentException e) {
                    // same with ThrowsAdvice
                    logger.info("Exception. Throws IllegalArgumentException");
                    throw e;
                }

    }

    private String getClassNameFrom(Class invokerClassName) {
        // Function that ....... To be continued JP

        // Add check for that string contains $$ and se.goteborg if not then
        // return fallback logger class.

        String[] classNameParts = invokerClassName.getName().split("$$");
        int positionOfPackageName = classNameParts[0].indexOf("se.jpab");
        String className = classNameParts[0].substring(positionOfPackageName);

        return className;
    }
}

Spring配置(spring.xml)

<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:mvc="http://www.springframework.org/schema/mvc"
       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.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


 <aop:aspectj-autoproxy proxy-target-class="true"/>
 <context:load-time-weaver/>
 <context:annotation-config />
 <context:component-scan base-package="se.jpab"/>


</beans>

1 个答案:

答案 0 :(得分:1)

您的第一个问题:

  

在日志编织时不包括私有方法   方法。是否允许弹簧的xml设置中的设置   要编织的私人方法还是有另外一种解决方法?

如果你想编织私有方法,请使用完整的AspectJ,其中包含特权方面,而不是Spring AOP。 Spring manual说:

  
    

如果您的拦截需要包括受保护/私有方法甚至是     构造函数,考虑使用Spring驱动的原生AspectJ编织     而不是Spring的基于代理的AOP框架。这构成了一个     不同模式的AOP使用具有不同的特性,所以一定要确定     在做出决定之前先熟悉编织。

  

您的第二个问题:

  

我必须包含要编织的所有包   META-INF / aop.xml为此能够工作。有没有设置   使用,以便可以为创建的所有类编织日志信息   在项目中,无需将包名称添加到aop.xml。

您可以使用..语法捕获包的所有子包,例如se.jpab.application..*甚至是se.jpab..*。您还可以将多个条件与布尔运算符组合在一起。有关示例,请参阅AspectJ documentation