zoukankan      html  css  js  c++  java
  • spring顾问包装通知

    前边说到了顾问就是通知,没有实践,这里就实践一下,证明一下。

    虽然可以说顾问就是通知,但是他们还是有的一定的区别的,通知是将目标类中所有的方法都进行的增强,而顾问却可以指定到特定的方法上,也就是说顾问的功能更加强大一些

    而包装的方式常用的有两种,一种是基于名字的(方法),一种是基于正则的(方法),他们都是通过目标类的方法名进行的包装。

    创建增强类

     1 /**
     2  * 增强类
     3  */
     4 public class Advice implements MethodBeforeAdvice, AfterReturningAdvice {
     5     @Override
     6     public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
     7         System.out.println("我是后置增强");
     8     }
     9 
    10     @Override
    11     public void before(Method method, Object[] objects, Object o) throws Throwable {
    12         System.out.println("我是前置增强");
    13     }
    14 }

    创建service接口

    1 public interface DoSome {
    2     void dosome();
    3     void say();
    4 }

    创建实现类

    public class DoSomeImpl implements DoSome{
        public void dosome(){
            System.out.println("我是service层");
        }
    
        @Override
        public void say() {
            System.out.println("你好,bdqn");
        }
    }

    由于两种增强方式的service层和增强类都是一样的这里我只写一次

    第一种根据方法名包装

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     5     <!--创建service层的bean-->
     6     <bean id="service" class="service.DoSomeImpl"></bean>
     7     <!--创建通知的bean-->
     8     <bean id="advice" class="advice.Advice"></bean>
     9     <!--顾问包装通知-->
    10     <bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
    11         <property name="advice" ref="advice"></property>
    12         <property name="mappedNames" value="say"></property>
    13     </bean>
    14     <!--创建代理工厂bean,并注入属性-->
    15     <bean id="factoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    16         <!--注入service实现类的bean-->
    17         <property name="target" ref="service"/>
    18         <!--注入通知的bean,注意这里不使用ref注入,只能是value属性,属性为avcisor 的bean的id属性-->
    19         <property name="interceptorNames" value="advisor"/>
    20     </bean>
    21 </beans>

    创建测试类

    public class Dome {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
            DoSome proxyFactory = (DoSome) context.getBean("factoryBean");//这里注入的是ProxyFactoryBean的id属性值
            proxyFactory.say();
            System.out.println(">>>>>>>>>>>两个方法的分割线>>>>>>>>>>>>");
            proxyFactory.dosome();
        }
    }

    第二种基于正则的方式

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     5     <!--创建service层的bean-->
     6     <bean id="service" class="service.DoSomeImpl"></bean>
     7     <!--创建通知的bean-->
     8     <bean id="advice" class="advice.Advice"></bean>
     9     <!--顾问包装通知-->
    10     <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    11         <property name="advice" ref="advice"></property>
    12         <property name="pattern" value=".*say.*"/>
    13     </bean>
    14     <!--创建代理工厂bean,并注入属性-->
    15     <bean id="factoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    16         <!--注入service实现类的bean-->
    17         <property name="target" ref="service"/>
    18         <!--注入通知的bean,注意这里不使用ref注入,只能是value属性,属性为通知类bean的id属性-->
    19         <property name="interceptorNames" value="advisor"/>
    20     </bean>
    21 </beans>

    测试类与第一种方式相同,结果自行验证,需要的pom节点

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.0.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>5.1.0.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.1.0.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-expression</artifactId>
                <version>5.1.0.RELEASE</version>
            </dependency>
            <!--以上4个是spring的核心-->
            <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.9.2</version>
            </dependency>

    每次写一个通知都需要手动去添加一个代理工厂也是很烦人的,那自然有简单的方式,只需要配置一次即可以了

    基于id名的代理生成器:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--创建service层的bean-->
        <bean id="service" class="service.DoSomeImpl"></bean>
        <!--创建通知的bean-->
        <bean id="advice" class="advice.Advice"></bean>
        <!--基于方法名的包装-->
        <bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
            <property name="advice" ref="advice"></property>
            <property name="mappedName" value="say"></property>
        </bean>
        <!--基于方法名的代理生成器-->
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames" value="service"></property>
            <property name="interceptorNames" value="advisor"/>
        </bean>
    </beans>

    默认的代理生成器

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--创建service层的bean-->
        <bean id="service" class="service.DoSomeImpl"></bean>
        <!--创建通知的bean-->
        <bean id="advice" class="advice.Advice"></bean>
        <!--顾问包装通知-->
        <bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="advice"></property>
            <property name="pattern" value=".*say.*"/>
        </bean>
        <!--基于方法名的代理生成器-->
       <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
           <property name="interceptorNames" value="service"/>
           <property name="beanName" value="advisor"/>
       </bean>
    </beans>

    由于代理工厂也被代理了,所以没有了代理工厂的id这里测试类需要做一定的改变

    public class Dome {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
            DoSome proxyFactory = (DoSome) context.getBean("service");
            proxyFactory.say();
            System.out.println(">>>>>>>>>>>两个方法的分割线>>>>>>>>>>>>");
            proxyFactory.dosome();
        }
    }

    自动代理生成器推荐使用第一种,第二种容易出bug,因为它默认会为xml文件中的所有bean节点创建工厂

  • 相关阅读:
    Node.js基础学习一之Get请求
    Node.js学习准备篇
    如何在eclipse添加SVN菜单
    Java泛型的好处
    mybatis多数据源配置
    Python map() 函数
    python split()使用方法
    pythom os 模块
    深浅copy
    小数据池
  • 原文地址:https://www.cnblogs.com/Tiandaochouqin1/p/10434379.html
Copyright © 2011-2022 走看看