美文网首页
Spring AOP注解@DeclareParents的使用

Spring AOP注解@DeclareParents的使用

作者: 仿若尘土 | 来源:发表于2019-03-14 13:45 被阅读0次

    [TOC]

    1. 概念

    Spring AOP提供的@Before@After@AfterReturning@AfterThrowingAround只对类的现有方法进行增强处理。如果需要对现有类增加新的方法,有两种方法可实现:

    1. 扩展现有类:实现简单,但如果对多个现有类进行扩展时,需增加多个类
    2. 使用@DeclareParents注解实现:实现复杂,可使用通配符匹配
      本文介绍@DeclareParents注解实现的增强。

    2. 通过@DeclareParents注解实现

    2.1 maven依赖

            <!--spring的context上下文即IoC容器-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <!--spring aop依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <!--spring测试依赖-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${spring.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!--junit依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    
            <!--spring aop依赖AspectJ-->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
            </dependency>
    

    2.2 实现

    1. 待增强功能
    package com.cui.springShizhan.ch4.DeclareParents;
    
    public interface IWaitingProxy {
        public void method();
    }
    
    package com.cui.springShizhan.ch4.DeclareParents;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class WaitingProxyImpl implements IWaitingProxy {
        @Override
        public void method() {
            System.out.println("现有方法");
        }
    }
    
    1. 代理类
    package com.cui.springShizhan.ch4.DeclareParents;
    
    public interface IDeclareParentProxy {
        public void declareParentProxy();
    }
    
    package com.cui.springShizhan.ch4.DeclareParents;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class DeclareParentProxyImpl implements IDeclareParentProxy{
        @Override
        public void declareParentProxy() {
            System.out.println("我是增强代理方法");
        }
    }
    
    1. 切面配置
    package com.cui.springShizhan.ch4.DeclareParents;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.DeclareParents;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class AspectJIntroductionAnnotationAdvice {
        @DeclareParents(value = "com.cui.springShizhan.ch4.DeclareParents.*", defaultImpl = DeclareParentProxyImpl.class)
        private IDeclareParentProxy iDeclareParentProxy;
    }
    

    说明:

    • value:相当于XML中的types-matching,待引入增强作用的类的表达式, 支持通配符
    • defaultImpl:引入增强的具体实现
    1. spring配置
    package com.cui.springShizhan.ch4.DeclareParents;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Configuration
    @ComponentScan("com.cui.springShizhan.ch4")
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class AppConfig {
    }
    
    1. 单元测试
    package springshizhan.ch4;
    
    import com.cui.springShizhan.ch4.DeclareParents.AppConfig;
    import com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy;
    import com.cui.springShizhan.ch4.DeclareParents.IWaitingProxy;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = AppConfig.class)
    public class DeclareParentsAnnotationTest {
        @Resource
        private IWaitingProxy iWaitingProxy;
    
        @Test
        public void test() {
            iWaitingProxy.method();
            IDeclareParentProxy iDeclareParentProxy = (IDeclareParentProxy) iWaitingProxy; 
            iDeclareParentProxy.declareParentProxy();
        }
    }
    /*结果
    现有方法
    我是增强代理方法
    */
    

    3. 通过XML配置实现

    主要区别为配置文件:
    方式1:

    <?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:c="http://www.springframework.org/schema/c"
           xmlns:p="http://www.springframework.org/schema/p" 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/context
            http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="iWaitingProxy" class="com.cui.springShizhan.ch4.DeclareParents.WaitingProxyImpl"/>
        <bean id="iDeclareParentProxy" class="com.cui.springShizhan.ch4.DeclareParents.DeclareParentProxyImpl"/>
    
        <aop:config proxy-target-class="true">
            <aop:aspect>
                <aop:declare-parents
                        types-matching="com.cui.springShizhan.ch4..*"
                        implement-interface="com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy"
                        delegate-ref="iDeclareParentProxy"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

    方式2:

    <?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:c="http://www.springframework.org/schema/c"
           xmlns:p="http://www.springframework.org/schema/p" 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/context
            http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="iWaitingProxy" class="com.cui.springShizhan.ch4.DeclareParents.WaitingProxyImpl"/>
    
        <aop:config proxy-target-class="true">
            <aop:aspect>
                <aop:declare-parents
                        types-matching="com.cui.springShizhan.ch4..*"
                        implement-interface="com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy"
                        default-impl="com.cui.springShizhan.ch4.DeclareParents.DeclareParentProxyImpl"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

    属性解释:

    • types-matching:待增强类的表达式,支持通配符
    • implement-interface:引入增强的方法所在的接口
    • delegate-ref:引入增强的实现bean的id(方式1
    • default-impl:引入增强的实现类的全路径名称(方式2,使用该方式,无需把增强类的Bean注入到Spring容器中)
      注:delegate-refdefault-impl仍选一个实现即可

    4. 参考

    1. Spring源码-AOP(八)-引入增强
    2. spring-AOP通过注解@DeclareParents引入新的方法
    3. 《Spring 实战》第4版

    相关文章

      网友评论

          本文标题:Spring AOP注解@DeclareParents的使用

          本文链接:https://www.haomeiwen.com/subject/swvfmqtx.html