zoukankan      html  css  js  c++  java
  • Spring5参考指南:AspectJ高级编程之Configurable

    遇到的问题

    前面的文章我们讲到了在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的博客

  • 相关阅读:
    encode 与 decode
    pthon_flask小汇总
    jquery 动态添加标签而且指定样式
    设置Myeclipse中的代码格式化、及保存时自动格式化
    a href="javascript:void(0)" 是什么意思?与 a href="#" 加不加上有什么区别?
    String类 与StringBuffer类
    Java中的String类与StringBuffer类
    获取系统的当前时间
    switch 中可以使用字符串当判断条件
    关于接口的那些事
  • 原文地址:https://www.cnblogs.com/flydean/p/12680380.html
Copyright © 2011-2022 走看看