Spring的@Configurable

今天我们学习一个比较少用到,但是也是比较强大的功能@Configurable。

大家都知道,在Spring容器里的对象可以通过@Autowired来注入,但是如果这个对象是你自己new出来的,恐怕很难通过@Autowired来获得对象了。

@Configurable这个注解就是为了给非Spring容器管理的对象提供注入Spring容器内对象的一个注解。

我们先看一下我们的一个普通对象,这个对象里我们注入一个Spring的ApplicationContext。然后标记为@Configurable。

@Configurable
public class User {
    @Autowired
    ApplicationContext applicationContext;
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString(){
        return Arrays.asList(applicationContext.getBeanDefinitionNames()).toString();
    }
}

这里我们重写toString()方法打印为显示容器里的bean名称。

然后我们修改启动类

@SpringBootApplication
@EnableSpringConfigured
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

此时我们需要的东西基本准备完成了,然后我们需要在pom文件添加

<!-- aspects 编译需要的依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <scope>provided</scope>
</dependency>
<!-- aspects 编译需要的依赖 end-->

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.7</version>

    <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>
            <phase>process-classes</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

我们写测试类来看看结果,

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
    @Test
    public void contextLoads() {
        User user=new User();
        System.out.println(user.toString());
    }
}

注意,这里我们的User对象是new出来的。我们看到运行后并没有报空指针异常,而是打印出了Spring容器对象名称。

[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, org.springframework.boot.test.mock.mockito.MockitoPostProcessor$SpyPostProcessor, org.springframework.boot.test.mock.mockito.MockitoPostProcessor, application, org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory, org.springframework.context.annotation.aspectj.SpringConfiguredConfiguration, org.springframework.context.config.internalBeanConfigurerAspect, org.springframework.boot.autoconfigure.AutoConfigurationPackages, org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration, org.springframework.boot.autoconfigure.condition.BeanTypeRegistry, propertySourcesPlaceholderConfigurer, org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$CglibAutoProxyConfiguration, org.springframework.aop.config.internalAutoProxyCreator, org.springframework.boot.autoconfigure.aop.AopAutoConfiguration, org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration, org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration, org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor, org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata, org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration, persistenceExceptionTranslationPostProcessor, org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration, spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties, org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration, taskExecutorBuilder, applicationTaskExecutor, spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties, org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration, taskSchedulerBuilder, spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, platformTransactionManagerCustomizers, spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties]

我们去target里面反编译class文件看看结果

@Configurable
public class User implements ConfigurableObject {
    @Autowired
    ApplicationContext applicationContext;
    private String name;
    private int age;

    public User() {
        JoinPoint var2 = Factory.makeJP(ajc$tjp_1, this, this);
        JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
        if (this != null && this.getClass().isAnnotationPresent(Configurable.class) && AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$before$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$1$e854fa65(this);
        }

        if (this != null && this.getClass().isAnnotationPresent(Configurable.class) && (this == null || !this.getClass().isAnnotationPresent(Configurable.class) || !AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class))) && AbstractDependencyInjectionAspect.ajc$if$6f1(var1)) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
        }

        if (!AnnotationBeanConfigurerAspect.ajc$if$bb0((Configurable)this.getClass().getAnnotation(Configurable.class)) && AbstractDependencyInjectionAspect.ajc$if$6f1(var2)) {
            AnnotationBeanConfigurerAspect.aspectOf().ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(this);
        }

    }
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return Arrays.asList(this.applicationContext.getBeanDefinitionNames()).toString();
    }
    static {
        ajc$preClinit();
    }
}

可以看到,Spring为我们添加了很多方法,这也就解释了为啥能注入spring bean的原因了。

源码链接icon-default.png?t=MBR7https://link.zhihu.com/?target=https%3A//github.com/yuebo/wechat-blog/tree/master/spring

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值