发现原因是因为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