前面的文章咱們講到了在Spring中使用Aspect。可是Aspect的都是Spring管理的Bean。 如今有一個問題,實際工做中,咱們常常會想new一個Bean,而後在這個Bean中注入Spring管理的其餘Bean。可是new出來的bean已經脫離Spring的管控了。php
該怎麼處理呢?java
Spring提供了一個@Configurable的註解,能夠實現這個功能,咱們看一個例子:git
@Configurable(autowire= Autowire.BY_NAME, preConstruction = true)
public class Account {
private static Logger log= LoggerFactory.getLogger(Account.class);
private String name;
@Autowired
private BeanA beanA;
public Account(){
log.info("init Account");
}
public Object getBeanA() {
return beanA;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
複製代碼
這裏定義了一個Account類,它裏面有依賴的BeanA,咱們想在new Account()的時候, 直接使用Spring注入的BeanA。github
preConstruction = true 表示依賴的Bean在構造函數調用以前就被注入了。spring
autowire= Autowire.BY_NAME 表示依賴的Bean是按名字來自動裝配。固然也能夠使用autowire= Autowire.BY_TYPE,按類型來裝配。apache
同時咱們須要開啓SpringConfig支持:app
@Configuration
@EnableSpringConfigured
public class AppConfig {
}
複製代碼
最後看下咱們怎麼調用:maven
public class ConfigurableApp {
private static Logger log= LoggerFactory.getLogger(ConfigurableApp.class);
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean-config.xml");
Account accountA=new Account();
log.info(accountA.getBeanA().toString());
}
}
複製代碼
輸出結果以下:函數
07:37:27.917 [main] INFO com.flydean.beans.Account - init Account
07:37:27.917 [main] INFO com.flydean.ConfigurableApp - com.flydean.beans.BeanA@54c5a2ff
複製代碼
能夠看到雖然Account是new出來的,可是BeanA依然被注入到實例中。ui
單獨使用@Configurable沒有任何做用。
Spring-Aspects.jar中的AnnotationBeanConfigurerAspect,纔是讓@Configurable起做用的根本。本質上,aspect是,「從用@Configurable註解的類型的新對象的初始化返回後,根據註解的屬性使用spring配置新建立的對象」。在此上下文中,「初始化」是指新實例化的對象(例如,用new運算符實例化的對象)以及正在進行反序列化的可序列化對象(例如,經過 readResolve())。
下面是最最重要的pom配置了,這裏我使用了aspectj-maven-plugin 這個插件來對spring-aspects.jar進行編織。 以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring5-core-workshop</artifactId>
<groupId>com.flydean</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>aop-advanced</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<!-- To define the plugin version in your parent POM -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
</plugin>
</plugins>
</pluginManagement>
<!-- To use the plugin goals in your POM or parent POM -->
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<outxml>true</outxml>
<verbose>true</verbose>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
<goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
複製代碼
本文的例子能夠參考aop-advanced
更多教程請參考 flydean的博客