aop执行两次的原因

时间:2020-12-21 18:52:00


JavaConfig方式配置没有此现象,而xml配置出现这样的问题。共同代码如下:

package springinaction.chapter4;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * @author JUANJUAN
 * @time 2018年1月8日 下午2:27:26
 */
@Aspect
public class Audience {

	@Pointcut("execution(** springinaction.chapter4.Performance.perform(..))")
	public void performance() {}
	@Before("performance()")
	public void silenceCellPhones() {
		System.out.println("Silencing cell phones");
	}
	@Before("performance()")
	public void takeSeats() {
		System.out.println("Taking seats");
	}
	@AfterReturning("performance()")
	public void applause() {
		System.out.println("CLAP CLAP CLAP");
	}
	@AfterThrowing("performance()")
	public void demandRefund() {
		System.out.println("Demanding a refund");
	}
}
package springinaction.chapter4;
/**
 * @author JUANJUAN
 * @time 2018年1月8日 下午2:34:27
 */
public interface Performance {
	void perform();
}
package springinaction.chapter4;

import org.springframework.stereotype.Component;

/**
 * @author JUANJUAN
 * @time 2018年1月8日 下午2:48:33
 */
@Component
public class SingPerformance implements Performance{

	@Override
	public void perform() {
		// TODO Auto-generated method stub
		System.out.println("Classic Music Performance on");
	}

}
JavaConfig配置类

package springinaction.chapter4;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
 * @author JUANJUAN
 * @time 2018年1月8日 下午2:35:27
 */
@Configuration
@ComponentScan
@EnableAspectJAutoProxy //启动AspectJ自动代理
public class ConcertConfig {
	@Bean
	public Audience audience() {
		return new Audience();
	}
}

xml配置文件

<?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:jdbc="http://www.springframework.org/schema/jdbc"
  xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" 
  xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
    http://www.springframework.org/schema/jee
    http://www.springframework.org/schema/jee/spring-jee.xsd
    http://www.springframework.org/schema/jdbc
    http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
	<context:component-scan base-package="springinaction.chapter4" />
	<aop:aspectj-autoproxy />
	<!--  在xml配置中,配置Audience后,aop执行了两次,因为生成了两个audience代理。移除这个bean或者在自动扫描中去除aop的类
	<bean class="springinaction.chapter4.Audience"/>
	-->
	
</beans>
测试类:

package springinaction.chapter4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @author JUANJUAN
 * @time 2018年1月8日 下午2:44:50
 */
public class AOPTest {
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration(classes=ConcertConfig.class)
	public static class JavaConfigTest{
		@Autowired
		private Performance perform;
		@Test
		public void test() {
			perform.perform();
		}
	}
	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration("classpath*:aop.xml")
	public static class XMLTest{
		@Autowired
		private Performance perform;
		@Test
		public void test() {
			perform.perform();
		}
	}
}

xml配置方式中移除
<bean class="springinaction.chapter4.Audience"/>
之后,aop执行恢复正常。应该是自动扫描时也创建了一个代理,导致容器中两个aop代理,执行了两次。

但是有一个疑问,就是JavaConfig配置类中也配置了自动扫描,却没有执行两次,移除JavaConfig配置类中的

@Bean
	public Audience audience() {
		return new Audience();
	}
后,aop失效,也就是说明JavaConfig配置类中ComponentScan并没有扫描被@Aspect注解的Audience。

而xml文件中的component-scan却扫描了被@Aspect注解的Audience。

这两个方式的实现方式是不一样的?哪里不一样?