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("\ncast to Printer\n");
        ((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

 

转载于:https://www.cnblogs.com/lvjianwei/p/7729207.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值