AOP 之 @DeclareParents的用法

前言

最近一直在看Spring框架文档,也对@DeclareParents注释有了初步的了解,所以这篇文章仅提供入门参考。

概念

通过注释@DeclareParents,可以提供强大的代理功能。那么如何理解这种代理功能呢?如下图所示,B其实就是代理类,用于增强类A的能力(如添加方法实现)。这里可能会有疑惑:为什么不在A类中直接添加想要的功能呢?

在面向切面编程(AOP)时,为了避免侵入性,减少对业务代码的结构影响,同时也遵循面向切面编程的思想,所以通过代理来增强被代理类的功能是更好的选择。面向对象编程的一个目的是,将非业务代码从业务代码中分离出来,那么应该通过代理实现增强被代理类,而不是将非业务代码(这里指通过代理增强被代理类的功能代码)写进业务代码模块中。

这里写图片描述

案例

通过以下案例,可以更好的理解。

代理类接口
package com.springboot.demo.entity;

public interface ProxyClass {
    void print();
}
代理类接口实现
package com.springboot.demo.entity;

public class ProxyClassImpl implements ProxyClass {
    public void print() {
        System.out.println("this is ProxyClass");
    }
}
被代理类
package com.springboot.demo.entity;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class Person {

    public void out(){
        System.out.println("hello");
    }
}

使用注释@DeclareParents建立代理关系

package com.springboot.demo.aop;

import com.springboot.demo.entity.ProxyClass;
import com.springboot.demo.entity.ProxyClassImpl;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;


@Component
@Aspect
public class AopExample {


    @DeclareParents(value = "com.springboot.demo.entity.Person",defaultImpl = ProxyClassImpl.class)
    ProxyClass proxy;


}

上面代码说明,Person类是被ProxyClassImpl类代理,实际上两者互为代理,可以通过测试验证

测试代码
package com.springboot.demo;

import com.springboot.demo.entity.Person;
import com.springboot.demo.entity.ProxyClass;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    Person person;

    @Autowired
    ProxyClass proxyClass2;
    
    @Test
    void contextLoads() {
        ProxyClass proxyClass = (ProxyClass) person;
        proxyClass.print();

        Person person2 = (Person) proxyClass2;
        person2.out();
    }

}

通过注释@Autowired,注入Person类和 ProxyClass接口的实例,然后对两者进行强制转型,然后调用转型后的类的方法,看看是否会报错。

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9h5Umcja-1583059597194)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200301165029444.png)]

Person类和ProxyClass`接口的实例,然后对两者进行强制转型,然后调用转型后的类的方法,看看是否会报错。

结果

[外链图片转存中…(img-9h5Umcja-1583059597194)]

通过结果,可以看到代理与被代理的关系是相互的,因为你可以通过代理类去得到被代理类的能力,反过来也成立。

你可能感兴趣的:(Spring)