AnnotationBeanConfigurerAspect
AnnotationBeanConfigurerAspect是一个AspectJ切面,使用AspectJ语言定义。
通过上下文获取该切面后,调用其实例方法configureBean()
,可对一个使用new关键字创建的对象进行配置,实现自动连线。
AnnotationBeanConfigureAspect本身需要由Spring进行配置(以便获得用于配置新对象的bean工厂的引用)。@EnableSpringConfigured注解专门实现该需求。
该切面属于制品spring-aspects
:
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
implementation 'org.springframework:spring-context:5.2.0.RELEASE'
implementation 'org.springframework:spring-aspects:5.2.0.RELEASE'
}
configureBean():
package bean
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Configurable
import org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.ComponentScan
import org.springframework.stereotype.Component
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig
@Component
@Configurable(preConstruction = true)
open class A {
@Autowired
open var ctx: ApplicationContext? = null
open fun foo() {
println(ctx)
}
}
@ExtendWith(SpringExtension::class)
@SpringJUnitConfig(ConfigurableTest::class)
@ComponentScan
@org.springframework.context.annotation.aspectj.EnableSpringConfigured
open class ConfigurableTest {
@Autowired lateinit var ctx: ApplicationContext
@Test fun main() {
A().foo() // null
ctx.getBean(A::class.java).foo() // not null
val aspect = ctx.getBean(AnnotationBeanConfigurerAspect::class.java)
val bean = A()
bean.foo() // null
aspect.configureBean(bean)
bean.foo() // not null
}
}
加载时编织
要启用Spring框架的LTW支持,你需要配置一个LoadTimeWeaver,通常通过使用@EnableLoadTimeWeaving注解完成。
@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan
@org.springframework.context.annotation.aspectj.EnableSpringConfigured // AnnotationBeanConfigureAspect本身需要由Spring进行配置(以便获得用于配置新对象的bean工厂的引用)
//@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED) // 要启用Spring框架的LTW支持,你需要配置一个LoadTimeWeaver,通常通过使用@EnableLoadTimeWeaving注解完成
//@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.DISABLED)
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.AUTODETECT) // 自动检测META-INF/aop.xml配置文件是否存在
open class JavaConfig : LoadTimeWeavingConfigurer {
// Implement LoadTimeWeavingConfigurer is optional. In default, DefaultContextLoadTimeWeaver will active.
override fun getLoadTimeWeaver(): LoadTimeWeaver {
return InstrumentationLoadTimeWeaver().apply {
println("inject -> $this")
}
}
}
加载时编织需要修改jvm选项,设置代理为spring-instrument,可在Gradle脚本中设置:
dependencies {
// AOP
// https://mvnrepository.com/artifact/org.aspectj/aspectjrt
implementation group: 'org.aspectj', name: 'aspectjrt', version: '1.9.6'
// https://mvnrepository.com/artifact/org.aspectj/aspectjweaver
implementation group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.6'
// Spring-instrument
runtimeOnly 'org.springframework:spring-instrument:5.2.0.RELEASE'
}
test {
// Setup the Java agent to Spring-instrument
def file_spring_instrument = sourceSets.test.runtimeClasspath.find { it.name.matches("spring-instrument-.*\\.jar") }
jvmArgs "-javaagent:$file_spring_instrument"
useJUnitPlatform()
}
@See: https://docs.gradle.org/current/userguide/building_java_projects.html#sec:feature_preview
META-INF/aop.xml
META-INF/aop.xml定义需要扫描、配置的类,格式如下:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="bean.*"/>
</weaver>
</aspectj>