遇到的问题

前面的文章我们讲到了在Spring中使用Aspect。但是Aspect的都是Spring管理的Bean。 现在有一个问题,实际工作中,我们经常会想new一个Bean,然后在这个Bean中注入Spring管理的其他Bean。但是new出来的bean已经脱离Spring的管控了。

该怎么处理呢?

@Configurable

Spring提供了一个@Configurable的注解,可以实现这个功能,我们看一个例子:

@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。

preConstruction = true 表示依赖的Bean在构造函数调用之前就被注入了。

autowire= Autowire.BY_NAME 表示依赖的Bean是按名字来自动装配。当然也可以使用autowire= Autowire.BY_TYPE,按类型来装配。

同时我们需要开启SpringConfig支持:

@Configuration
@EnableSpringConfigured
public class AppConfig {
}

最后看下我们怎么调用:

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依然被注入到实例中。

原理

单独使用@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的博客

Spring5参考指南:AspectJ高级编程之Configurable的更多相关文章

  1. Spring5参考指南:AspectJ注解

    文章目录 什么是AspectJ注解 启用AOP 定义Aspect 定义Pointcut 切入点指示符(PCD) 切入点组合 Advice 访问JoinPoint Advice参数 Advice参数和泛 ...

  2. Spring5参考指南:IOC容器

    文章目录 为什么使用Spring5 什么是IOC容器 配置元数据 实例化容器 XML嵌套 groovy bean定义DSL 使用容器 最近在翻译Spring Framework Documentati ...

  3. Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)

    Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享)  点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...

  4. Python Flask高级编程之从0到1开发《鱼书》精品项目 ☝☝☝

    Python Flask高级编程之从0到1开发<鱼书>精品项目 ☝☝☝ 一 .安装环境我们使用 flask web框架,并用 sqlalchemy来做数据库映射,并使用 migrate做数 ...

  5. Python Flask高级编程之从0到1开发《鱼书》精品项目 ✍✍✍

    Python Flask高级编程之从0到1开发<鱼书>精品项目  一 .安装环境我们使用 flask web框架,并用 sqlalchemy来做数据库映射,并使用 migrate做数据迁移 ...

  6. Python Flask高级编程之从0到1开发《鱼书》精品项目

    Python Flask高级编程之从0到1开发<鱼书>精品项目     整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感 ...

  7. Spring5参考指南:依赖注入

    文章目录 依赖注入 依赖注入的配置详解 depends-on lazy-init 自动装载 方法注入 依赖注入 依赖注入就是在Spring创建Bean的时候,去实例化该Bean构造函数所需的参数,或者 ...

  8. Spring5参考指南:AOP代理

    文章目录 AOP代理 AOP Proxies原理 AOP代理 通常来说Spring AOP有两种代理方式,一种默认的JDK代理,只能代理接口,一种是CGLIB代理,可以代理具体的类对象. Spring ...

  9. Spring5参考指南:基于Schema的AOP

    文章目录 基于Schema的AOP 定义Aspect 定义Pointcut 定义Advice advice参数 Advisors 基于Schema的AOP 上篇文章我们讲到了使用注解的形式来使用Spr ...

随机推荐

  1. B - Bound Found POJ - 2566(尺取 + 对区间和的绝对值

    B - Bound Found POJ - 2566 Signals of most probably extra-terrestrial origin have been received and ...

  2. 关于C#三层架构增删改查中的“删除”问题

    序: 刚学习C#,经过一段时间学习,现在正在做一个简单的前后台联通的项目(主要是C#三层架构实现增删改查).分享一点儿小经验,也供自己以后可以回头看看自己的码农之路. 内容: 主要分享的是一条删除会用 ...

  3. PTA | 1019 数字黑洞 (20分)

    给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有" ...

  4. echarts以地图形式显示中国疫情情况实现点击省份下钻

    首先要导入对应的包.下钻用到各个省份的json文件等内容导入之后进行相关的操作. 首先是从数据库中读取相应的数据文件.通过list方式.只有在ser出转化为json文件.在jsp页面通过ajax来进行 ...

  5. redis 非关系型数据库

    redis 类型,数据存在磁盘里面,所以存储速度比较快,其他数据类型还是存储在数据库所以比较慢些 链接redis数据库: r=redis.Redis(host="%%%%%%%", ...

  6. [一起面试AI]NO.9 如何判断函数凸或非凸

    首先定义凸集,如果x,y属于某个集合M,并且所有的θx+(1-θ)f(y)也属于M,那么M为一个凸集.如果函数f的定义域是凸集,并且满足 f(θx+(1-θ)y)≤θf(x)+(1-θ)f(y) 则该 ...

  7. 使用基于vuecli创建的目录推送到指定远程分支

    笔者使用vuecli创建项目目录以后,在想将该目录提交到远程仓库时发现行不通,在忙活了一下午以后写下此文 1.github上新建一空分支,然后克隆该分支地址:  https://github.com/ ...

  8. split(resource,limit) 中limit 的含义

    limit 参数控制模式应用的次数,因此影响结果数组的长度.如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后项将包含超出最后匹配的定界符的所有输入 ...

  9. Python的深浅copy详解

    Python的深浅copy详解 目录 Python的深浅copy详解 一.浅copy的原理 1.1 浅copy的定义 1.2 浅copy的方法 二.深copy的原理 2.1 深copy的定义 2.2 ...

  10. 记一次错误 POST http://127.0.0.1:8000/auth/signup/ 500 (Internal Server Error)

    错误环境: 1,ajax 发送 post 请求调用 views 的视图 xfzajax.post({ 'url': '/xfzauth/signup/', 'data': { 'telephone': ...