0

我已经构建了一个应用程序来测试围绕类注入日志信息(进入和退出)。我已经使用 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。正如我所说,除了上述两个问题外,一切都很好。请帮助我。

应用程序.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);
    }   


}

位置.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.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>
4

1 回答 1

2

你的第一个问题:

当日志围绕方法编织时,不包括私有方法。spring 的 xml 设置中是否有允许编织私有方法的设置,或者是否有其他方法可以解决这个问题?

如果您想编织私有方法,请使用完整的 AspectJ 并在其中使用特权方面,而不是 Spring AOP。Spring手册说:

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

你的第二个问题:

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

您可以使用..语法(例如se.jpab.application..*,甚至se.jpab..*. 您还可以将多个条件与布尔运算符结合起来。有关示例,请参阅AspectJ 文档

于 2013-07-13T12:15:26.670 回答