• Spring 实战-第四章-4.3 使用注解引入新方法 Introductions&@DeclareParents


    @DeclareParents非常有意思,单独拿出来,这个可以给实现相同接口的类增加新的共同接口,

    这样在不侵入原有代码的情况下,转换成其他类型并拥有新的方法。

    这个功能在Spring AOP文档中叫做Introductions:

    Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare that advised objects implement a given interface, and to provide an implementation of that interface on behalf of those objects.
    An introduction is made using the @DeclareParents annotation. This annotation is used to declare that matching types have a new parent (hence the name). For example, given an interface UsageTracked, and an implementation of that interface DefaultUsageTracked, the following aspect declares that all implementors of service interfaces also implement the UsageTracked interface.

    The interface to be implemented is determined by the type of the annotated field. The value attribute of the @DeclareParents annotation is an AspectJ type pattern :- any bean of a matching type will implement the UsageTracked interface. Note that in the before advice of the above example, service beans can be directly used as implementations of the UsageTracked interface. 

    继续使用CompactDisc和其实现BlankDisc

    CompactDisc

    package main.java.soundsystem;
    public interface CompactDisc {
        void play();
        void playTrack(Integer trackNumber);
    }

    BlankDisc

    package main.java.soundsystem;
    
    import java.util.List;
    
    public class BlankDisc implements  CompactDisc{
    
        private  String title;
    
        private  String artist;
    
        private List<String> tracks;
    
        public BlankDisc setTitle(String title) {
            this.title = title;
            return this;
        }
    
        public BlankDisc setArtist(String artist) {
            this.artist = artist;
            return this;
        }
    
        public String getTitle() {
            return title;
        }
    
        public String getArtist() {
            return artist;
        }
    
        public void setTracks(List<String> tracks) {
            this.tracks = tracks;
        }
    
        public void play() {
            System.out.println("Playing " + title + " by " + artist);
            if(tracks!=null) {
                for (String track : tracks) {
                    System.out.println("-Track: " + track);
                }
            }
        }
    
        @Override
        public void playTrack(Integer trackNumber) {
            System.out.println("Playing "+tracks.get(trackNumber-1));
        }
    
    
    }

    定义一个新的Printer接口及其实现CDPrinter

    package main.java.soundsystem;
    
    public interface Printer {
        void printCover();
    }
    package main.java.soundsystem;
    
    public class CDPrinter implements Printer {
        @Override
        public void printCover() {
            System.out.println("print CD cover..."+Time);
        }
    
        public String getTime() {
            return Time;
        }
    
        public CDPrinter setTime(String time) {
            Time = time;
            return this;
        }
    
        private String Time;
    }

    那么如何在不修改CompactDisc及其实现的情况下,增加新的方法呢?使用@DeclareParent,使用Java代码配置。

    @DeclareParents有两个参数value,defaultImpl,

    value表示要为哪些类增加新的父类接口,最后的“+”表示对所有实现CompactDisc接口的类增加接口,

    defaultImpl表示新增接口的默认实现,这里新增接口就是被增加标签的Printer接口,

    这样所有实现CompactDisc接口的类,都引入了Printer接口,并且拥有了Printer中的方法。

    package main.java.soundsystem;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class CDPrinterAspect {
        @DeclareParents(value = "main.java.soundsystem.CompactDisc+",defaultImpl =CDPrinter.class)
        public static Printer printer;
    }

    增加xml配置,注意配置中并没有声明Printer对应的Bean。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="main.java.soundsystem"/>
        <aop:aspectj-autoproxy/>
    
        <bean id="blankDisc"  class="main.java.soundsystem.BlankDisc">
            <property name="title" value="Sgt. Pepper's Lonely Heart Club Band"/>
            <property name="artist" value="the Beatles"/>
            <property name="tracks">
                <list>
                    <value>Sgt. Pepper's Lonely Hearts Club Band</value>
                    <value>With a Little Help from My Friends</value>
                    <value>Lucy in the Sky with Diamonds</value>
                    <value>Getting Better</value>
                    <value>Fixing a Hole</value>
                </list>
            </property>
        </bean>
    </beans>

    具体使用,通过上下文使用BlankDisc生成了了一个CompactDisc的实例,然后显式转换为Printer对象,并且使用其中由CDPrinter实现的方法,

    package main.java.soundsystem;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class main {
    
        public static void main(String[] args) {
    
            ApplicationContext context = new ClassPathXmlApplicationContext("TrackCounterConfig.xml");
    
            CompactDisc cd=(CompactDisc)context.getBean("blankDisc");
            cd.play();
            System.out.println("
    cast to Printer
    ");
            ((Printer)cd).printCover();
        }
    }

    结果:

    Playing Sgt. Pepper's Lonely Heart Club Band by the Beatles
    -Track: Sgt. Pepper's Lonely Hearts Club Band
    -Track: With a Little Help from My Friends
    -Track: Lucy in the Sky with Diamonds
    -Track: Getting Better
    -Track: Fixing a Hole
    
    cast to Printer
    
    print CD cover...null
  • 相关阅读:
    001 云开发基础
    HttpClient 调用外部接口(简单实用)
    MD5加密(简单实现_可自行扩展)
    SAA C02考点梳理
    支配树
    CF1320E 题解
    dp套dp
    20210705模拟赛总结
    20210703模拟赛
    20210629模拟赛总结
  • 原文地址:https://www.cnblogs.com/lvjianwei/p/7729207.html
Copyright © 2020-2023  润新知