Spring实战08——为bean对象引入新方法

17 篇文章 0 订阅

在前面的切面学习中,注意到可以在对象.方法运行前后引入切面,执行通知代码,这本来就执行了多个方法,看起来却是像是对象的多个方法。切面只是实现了它们所包装的bean 相同接口的代理,如果除了实现这些接口,代理也能暴露新接口的话,切面所通知的bean看起来像是实现了新的接口,即便底层实现类并没有实现这些接口也无所谓。

当引入接口的方法即通知被调用时,代理会把此调用委托给实现了新接口的某个其他对象。实际上,一个bean的实现被拆分为多个类中。

 


实例:表演实现类只有play 方法,现需要有重新表演的方法 replay。需要有两个接口,一个父接口和一个子接口。

1.表演接口

package com.qhf.aop.example06;

public interface Performance {
    void play();
}

2.表演实现类

import org.springframework.stereotype.Component;

@Component
public class PerformanceImpl implements Performance {

    @Override
    public void play() {
        System.out.println("playing...");
    }
}

3.定义一个重新表演接口

public interface Reperformance {
    void replay();
}

4.重新表演实现类

public class ReperformanceImpl implements Reperformance {
    @Override
    public void replay() {
        System.out.println("replaying...");
    }
}

5.子接口的引入,相当于表演有两个方法,play 和 replay 方法

*@DeclareParents 注解,字面可理解为声明父母,即为value 值的类型的bean 引入该接口。

*value 值指定父接口,+ 号是作为子类型,即所有Performance 子类型

*defaultImpl 指定用哪个bean 作为实现类来引入

*Reperformance reperformance 中声明的bean 自动装配为指定defaultImpl 的类

@Component
@Aspect
public class ReperformanceIntorducer {

    @DeclareParents(value = "com.qhf.aop.example06.Performance + ", defaultImpl = ReperformanceImpl.class)
    public static Reperformance reperformance;
}

6.配置类

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class AopConfig {
}

7.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AopConfig.class)
public class Test {

    @Autowired
    private Performance performance;

    @org.junit.Test
    public void test(){
        performance.play();

        Reperformance r = (Reperformance) performance;//向下转型为子接口类
        r.replay();
    }
}

注意在ReperformanceImpl 中没有标注@Component,因为它在切面代理类ReperformanceIntorducer 中通过@DeclareParents 注解,值是.class说明是用字节码文件来装配到 reperformance 引用对象中。

只需通过父接口的实现类引用,向下转型为子接口类,便可以访问父接口引入的新方法。

7.结果

playing...
replaying...

 


xml配置

1.配置类

@Configuration
@ImportResource("classpath:aop/example07/aop.xml")
public class AopConfig {
}

2.切面类

public class ReperformanceIntorducer {

}

3.其他注解全部去除

4.xml文件

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 启动切面代理 -->
    <aop:aspectj-autoproxy/>

    <!-- 父接口实现类bean -->
    <bean id="performanceImpl" class="com.qhf.aop.example07.PerformanceImpl"/>
    <!-- 切面代理类bean -->
    <bean id="reperformanceIntorducer" class="com.qhf.aop.example07.ReperformanceIntorducer"/>

    <aop:config>
        <!-- 相当于@Aspect 注解在声明切面的类 -->
        <aop:aspect id="reperformanceIntorducer">

            <!-- types-matching:需要添加新功能的父接口 -->
            <!-- implement-interface:含新功能的子接口 -->
            <!-- default-impl:直接标识委托,即子接口的实现类,通过字节码文件装配,不需要有bean -->
            <!-- delegate-ref:间接标识委托,即子接口的实现类,需要有子接口的实现类的bean -->
            <aop:declare-parents
                    types-matching="com.qhf.aop.example07.Performance+"
                    implement-interface="com.qhf.aop.example07.Reperformance"
                    default-impl="com.qhf.aop.example07.ReperformanceImpl"/>

        </aop:aspect>
    </aop:config>
</beans>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值