Spring Aop遇到一个奇怪的问题,执行代理,会额外创建一个代理的类,然后获取代理bean却是一个新的bean。

发现原因是因为eclipse的builders中缺少了JavaBuilder,如下图,当前的builder是AspectJ Builder,通过此builder编译出的代码会有单独的代理类,并不是Bean出来的。

修改配置文件添加上Java Builder,使用Java Builder进行编译。则会正常。

总结:

使用AspectJ builder 编译的代码会额外的多创建一个代理类。

 

但是,如果不使用AspectJ Builder编译,如下代码将会报错。如何解决,暂时还没有找到办法

 

分析:

Java Builder 编译:运行期织入

需要定义切面类的Bean,不定义则不会织入。

public class TrackCounterConfig {

	@Bean
	public TrackCounter trackCounter() {
		return new TrackCounter();
	}

}

定义多个bean则多个bean会同时进行织入。

public class TrackCounterConfig {
	
	@Bean
	public CompactDisc sgtPeppers() {
		BlackDisc cd = new BlackDisc();
		cd.setTitle("Sgt. pepper's Lonely Hearts Club Band");
		cd.setArtist("The Beatles");
		return cd;
	}
	
	@Bean
	@Primary
	public TrackCounter trackCounter() {
		return new TrackCounter();
	}
	
	@Bean
	public TrackCounter trackCounter2() {
		return new TrackCounter();
	}

}

 

AspectJ Builder编译:编译器织入

无需单独定义切面类的Bean,定义也没有用,运行期也不会对创建的bean进行织入。看到的效果:在切面类的构造函数打印,会看到程序运行,多调用一次构造函数。如果没有创建bean,会有一次调用。如果创建了bean,会比创建的bean多一次调用。并且新创建的这些bean不会织入。也就不会有函数拦截。

???如果获取这个切面类的对象需要再网上再查询一些资料。

 

完整测试代码与打印输出:

需要被拦截的接口

package soundsystem;

public interface CompactDisc {
	void playTrack(int trackNumber);
}

需要被拦截的类

package soundsystem;

public class BlackDisc implements CompactDisc {
	
	private String title = "";
	private String artist = "";
	
	public String getTitle() {
		return title;
	}

	public String getArtist() {
		return artist;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public void setArtist(String artist) {
		this.artist = artist;
	}

	@Override
	public void playTrack(int trackNumber) {
		System.out.println("track " + trackNumber + " play.");
	}

}

切面类:

package soundsystem;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TrackCounter {
	private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>();
	
	private static int allocId = 0;
	private int id = 0;
	
	public TrackCounter() {
		this.id = ++allocId;
		System.out.println("create TrackCounter " + this.id);
	}
	
	public int getId() {
		return id;
	}

	@Pointcut("execution(* soundsystem.CompactDisc.playTrack(int)) && args(trackNumber)")
	public void trackPlayed(int trackNumber) {}
	
	@Before("trackPlayed(trackNumber)")
	public void countTrackBefore(int trackNumber) {
		int currentCount = getPlayCount(trackNumber);
		System.out.println("countTrackBefore trackNumber:" + trackNumber + "=" + currentCount);
		
		trackCounts.put(trackNumber, currentCount+1);
	}
	
	@After("trackPlayed(trackNumber)")
	public void countTrackAfter(int trackNumber) {
		int currentCount = getPlayCount(trackNumber);
		System.out.println("countTrackAfter trackNumber:" + trackNumber + "=" + currentCount);
	}
	
	public int getPlayCount(int trackNumber) {
		return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
	}
}

配置类:需要添加@EnableAspectJAutoProxy创建代理

package soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Primary;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class TrackCounterConfig {
	
	@Bean
	public CompactDisc sgtPeppers() {
		BlackDisc cd = new BlackDisc();
		cd.setTitle("Sgt. pepper's Lonely Hearts Club Band");
		cd.setArtist("The Beatles");
		return cd;
	}
	
	@Bean
	@Primary
	public TrackCounter trackCounter() {
		return new TrackCounter();
	}

}

测试类:

package soundsystem;

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;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=TrackCounterConfig.class)
public class TrackCounterTest {

	@Autowired
	private CompactDisc cd;
	
	@Autowired
	private TrackCounter counter;
	
	@Test
	public void testTrackCounter() {
		cd.playTrack(1);
		cd.playTrack(2);
		cd.playTrack(3);
		cd.playTrack(3);
		cd.playTrack(3);
		cd.playTrack(3);
		cd.playTrack(7);
		cd.playTrack(7);
		
		for (int i=1; i<=7; ++i) {
			int count = counter.getPlayCount(i);
			System.out.println(i + " : " + count);
		}
	}
}

Java Builder结果输出:

9月 07, 2019 3:45:12 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 3:45:12 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 3:45:12 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.GenericApplicationContext@45ca843: startup date [Sat Sep 07 15:45:12 CST 2019]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$2 (file:/E:/hz/github/SpringLibs/spring-core-4.0.4.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
create TrackCounter 1
countTrackBefore trackNumber:1=0
track 1 play.
countTrackAfter trackNumber:1=1
countTrackBefore trackNumber:2=0
track 2 play.
countTrackAfter trackNumber:2=1
countTrackBefore trackNumber:3=0
track 3 play.
countTrackAfter trackNumber:3=1
countTrackBefore trackNumber:3=1
track 3 play.
countTrackAfter trackNumber:3=2
countTrackBefore trackNumber:3=2
track 3 play.
countTrackAfter trackNumber:3=3
countTrackBefore trackNumber:3=3
track 3 play.
countTrackAfter trackNumber:3=4
countTrackBefore trackNumber:7=0
track 7 play.
countTrackAfter trackNumber:7=1
countTrackBefore trackNumber:7=1
track 7 play.
countTrackAfter trackNumber:7=2
1 : 1
2 : 1
3 : 4
4 : 0
5 : 0
6 : 0
7 : 2

AspectJ Builder输出结果:

9月 07, 2019 3:45:57 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 3:45:57 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 3:45:57 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.GenericApplicationContext@1ed1993a: startup date [Sat Sep 07 15:45:57 CST 2019]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$2 (file:/E:/hz/github/SpringLibs/spring-core-4.0.4.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
create TrackCounter 1
create TrackCounter 2
countTrackBefore trackNumber:1=0
track 1 play.
countTrackAfter trackNumber:1=1
countTrackBefore trackNumber:2=0
track 2 play.
countTrackAfter trackNumber:2=1
countTrackBefore trackNumber:3=0
track 3 play.
countTrackAfter trackNumber:3=1
countTrackBefore trackNumber:3=1
track 3 play.
countTrackAfter trackNumber:3=2
countTrackBefore trackNumber:3=2
track 3 play.
countTrackAfter trackNumber:3=3
countTrackBefore trackNumber:3=3
track 3 play.
countTrackAfter trackNumber:3=4
countTrackBefore trackNumber:7=0
track 7 play.
countTrackAfter trackNumber:7=1
countTrackBefore trackNumber:7=1
track 7 play.
countTrackAfter trackNumber:7=2
1 : 0
2 : 0
3 : 0
4 : 0
5 : 0
6 : 0
7 : 0

修改配置,声明多个切面bean:

package soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Primary;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class TrackCounterConfig {
	
	@Bean
	public CompactDisc sgtPeppers() {
		BlackDisc cd = new BlackDisc();
		cd.setTitle("Sgt. pepper's Lonely Hearts Club Band");
		cd.setArtist("The Beatles");
		return cd;
	}
	
	@Bean
	public TrackCounter trackCounter() {
		return new TrackCounter();
	}
	
	@Bean
	@Primary
	public TrackCounter trackCounter2() {
		return new TrackCounter();
	}

}

Java Builder结果输出:

创建了2个bean,并且都会进行织入。

9月 07, 2019 4:12:18 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 4:12:18 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 4:12:18 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.GenericApplicationContext@45ca843: startup date [Sat Sep 07 16:12:18 CST 2019]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$2 (file:/E:/hz/github/SpringLibs/spring-core-4.0.4.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
create TrackCounter 1
create TrackCounter 2
countTrackBefore trackNumber:1=0
countTrackBefore trackNumber:1=0
track 1 play.
countTrackAfter trackNumber:1=1
countTrackAfter trackNumber:1=1
countTrackBefore trackNumber:2=0
countTrackBefore trackNumber:2=0
track 2 play.
countTrackAfter trackNumber:2=1
countTrackAfter trackNumber:2=1
countTrackBefore trackNumber:3=0
countTrackBefore trackNumber:3=0
track 3 play.
countTrackAfter trackNumber:3=1
countTrackAfter trackNumber:3=1
countTrackBefore trackNumber:3=1
countTrackBefore trackNumber:3=1
track 3 play.
countTrackAfter trackNumber:3=2
countTrackAfter trackNumber:3=2
countTrackBefore trackNumber:3=2
countTrackBefore trackNumber:3=2
track 3 play.
countTrackAfter trackNumber:3=3
countTrackAfter trackNumber:3=3
countTrackBefore trackNumber:3=3
countTrackBefore trackNumber:3=3
track 3 play.
countTrackAfter trackNumber:3=4
countTrackAfter trackNumber:3=4
countTrackBefore trackNumber:7=0
countTrackBefore trackNumber:7=0
track 7 play.
countTrackAfter trackNumber:7=1
countTrackAfter trackNumber:7=1
countTrackBefore trackNumber:7=1
countTrackBefore trackNumber:7=1
track 7 play.
countTrackAfter trackNumber:7=2
countTrackAfter trackNumber:7=2
1 : 1
2 : 1
3 : 4
4 : 0
5 : 0
6 : 0
7 : 2

AspectJ Builder输出结果:

创建了3个bean,但只有第一个织入了。

9月 07, 2019 4:10:04 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 4:10:04 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners
信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.
9月 07, 2019 4:10:05 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.GenericApplicationContext@45ca843: startup date [Sat Sep 07 16:10:05 CST 2019]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$2 (file:/E:/hz/github/SpringLibs/spring-core-4.0.4.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
create TrackCounter 1
create TrackCounter 2
create TrackCounter 3
countTrackBefore trackNumber:1=0
track 1 play.
countTrackAfter trackNumber:1=1
countTrackBefore trackNumber:2=0
track 2 play.
countTrackAfter trackNumber:2=1
countTrackBefore trackNumber:3=0
track 3 play.
countTrackAfter trackNumber:3=1
countTrackBefore trackNumber:3=1
track 3 play.
countTrackAfter trackNumber:3=2
countTrackBefore trackNumber:3=2
track 3 play.
countTrackAfter trackNumber:3=3
countTrackBefore trackNumber:3=3
track 3 play.
countTrackAfter trackNumber:3=4
countTrackBefore trackNumber:7=0
track 7 play.
countTrackAfter trackNumber:7=1
countTrackBefore trackNumber:7=1
track 7 play.
countTrackAfter trackNumber:7=2
1 : 0
2 : 0
3 : 0
4 : 0
5 : 0
6 : 0
7 : 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值