@DeclareParents注解详解

@DeclareParents的作用

@DeclareParents注解是spring AOP(切面)功能提供一种组件,它可以在代理目标类上增加新的行为(新增新的方法)。可能你看到这里会有点蒙,没关系我们看下面的栗子,应该就清楚明白了。

@DeclareParents的应用demo

首先我们先通过一张图简单的理解一下,@DeclareParents注解实现的思路(注: 该图来源于《Spring in action中文版》一书,想要资料可以联系我)。
在这里插入图片描述

被代理的类(现有的行为-方法)

package com.swh.test.delareParents;

/**
 *  现有行为方法
 */
public interface IPay {
	void pay();
}

package com.swh.test.delareParents;

import org.springframework.stereotype.Component;

@Component("wechatPay")
public class WechatPay implements IPay{
	@Override
	public void pay() {
		System.out.println("wechat pay");
	}
}

代理增强类

package com.swh.test.delareParents;

/**
 *  增强的行为方法
 */
public interface IPayEnhance {
	void payType();
}

package com.swh.test.delareParents;

import org.springframework.stereotype.Component;

/**
 *  增强类的实现
 */
@Component
public class WechatPayEnhance implements IPayEnhance{
	@Override
	public void payType() {
		System.out.println("this pay type is wechat!");
	}
}

组装类

package com.swh.test.delareParents;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class PayAspectJ {

	@DeclareParents(value = "com.swh.test.delareParents.IPay+",defaultImpl = WechatPayEnhance.class)
	public IPayEnhance wechatPayEnhance;
}

bean的配置类

package com.swh.test.delareParents;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class AnnotationConfig {
}

@EnableAspectJAutoProxy 注解的作用启用AspectJ自动代理,会为使用@Aspect注解的bean创建一个代理,如果没有这个注解,则从spring获取bean时获取的原始类,本栗子中代理的是 IPay 接口。spring在创建WechatPay 类时,会创建一个代理类。

调用者

package com.swh.test;

import com.swh.test.delareParents.IPay;
import com.swh.test.delareParents.IPayEnhance;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestAA {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("com.swh.test");
		IPay wechatPay = (IPay) annotationConfigApplicationContext.getBean("wechatPay");
		wechatPay.pay();
		IPayEnhance wechatPayEnhance = (IPayEnhance) wechatPay;
		wechatPayEnhance .payType();
	}
}

执行结果分析

在这里插入图片描述
根据执行过程中的debug可见,从spring容器中获取的wechatPay bean是一个代理对象,并且实现了两个接口,分别是IPay 和 IPayEnhance ,因此这个代理类则拥有了IPay和IPayEnhance两种接口的行为。

@DeclareParents 的结构

@DeclareParents注解由三部分组成:

  • value 属性指定了哪种类型的bean要引入新的接口行为。(注:本栗子中value是IPay 并在IPay后面多了一个+,该+标识IPay下面的所有子类型,而不是IPay本身)
  • defaultImpl 属性指定了新提供的行为接口的实现类。本栗子我们引入的是WechatPayEnhance类
  • @DeclareParents 标注的类标识需要引入的新提供的行为接口

@DeclareParents 小结

@DecalereParents 可以为已经存在的Bean扩展新的行为方法,有的人会问为什么不直接在原始的接口中新加方法。当然这种也是可以的,但是这样做有个问题,加入原始接口下面有好多实现类,则需要对所有的实现类进行修改。这样做功能能够完成,但是从设计角度来看并不是最好的做法。况且有的时候根本没有机会修改所有的实现类,比如假如引用的原始类是第三方提供的并且没有源码。这种情况就没有办法通过直接扩展原始类来解决问题。当然还有其他的的应用场景,大家有什么不同的见解或者有不明白的地方,可以在评论区留言评论,我们一起交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值