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

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

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

创建增强类

 /**
* 增强类
*/
public class Advice implements MethodBeforeAdvice, AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("我是后置增强");
} @Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("我是前置增强");
}
}

创建service接口

 public interface DoSome {
void dosome();
void say();
}

创建实现类

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

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

第一种根据方法名包装

 <?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="mappedNames" value="say"></property>
</bean>
<!--创建代理工厂bean,并注入属性-->
<bean id="factoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--注入service实现类的bean-->
<property name="target" ref="service"/>
<!--注入通知的bean,注意这里不使用ref注入,只能是value属性,属性为avcisor 的bean的id属性-->
<property name="interceptorNames" value="advisor"/>
</bean>
</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();
}
}

第二种基于正则的方式

 <?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,并注入属性-->
<bean id="factoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--注入service实现类的bean-->
<property name="target" ref="service"/>
<!--注入通知的bean,注意这里不使用ref注入,只能是value属性,属性为通知类bean的id属性-->
<property name="interceptorNames" value="advisor"/>
</bean>
</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节点创建工厂

spring顾问包装通知的更多相关文章

  1. Spring——顾问封装通知

    通知(advice)是Spring中的一种比较简单的切面,只能将切面织入到目标类的所有方法中,而无法对指定方法进行增强 顾问(advisor)是Spring提供的另外一种切面,可以织入到指定的方法中  ...

  2. Spring顾问、IOC注解和注解增强

    一.顾问 通知的一种表现方式(顾问包装通知/增强) Advisor: 名称匹配方法: NameMecthMethodPointcutAdvisor 1.定义了一个业务类 package cn.spri ...

  3. Spring中的通知(Advice)和顾问(Advisor)

    在Spring中,目前我学习了几种增强的方式,和大家分享一下 之前的话: 1.AOP  (Aspect  Oriented Programming  面向切面编程) 在软件业,AOP为Aspect O ...

  4. Spring笔记07(Spring AOP的通知advice和顾问advisor)

    1.Spring AOP的通知advice 01.接口代码: package cn.pb.dao; public interface UserDao { //主业务 String add(); //主 ...

  5. spring aop 环绕通知around和其他通知的区别

    前言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知   是不能决定的,他们只 ...

  6. Spring AOP 四大通知

    Spring AOP 四大通知 Spring 3.X 以前 1.前置通知,实现  MethodBeforeAdvice 接口,重写 public  void  before(Method  metho ...

  7. [转载] spring aop 环绕通知around和其他通知的区别

    前言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知   是不能决定的,他们只 ...

  8. spring aop环绕通知

    [Spring实战]—— 9 AOP环绕通知   假如有这么一个场景,需要统计某个方法执行的时间,如何做呢? 典型的会想到在方法执行前记录时间,方法执行后再次记录,得出运行的时间. 如果采用Sprin ...

  9. Spring AOP--返回通知,异常通知和环绕通知

    在上篇文章中学习了Spring AOP,并学习了前置通知和后置通知.地址为:http://www.cnblogs.com/dreamfree/p/4095858.html 在本文中,将继续上篇的学习, ...

随机推荐

  1. VUE,index key v-for

    列表渲染语法  v-forv-for 循环对象 <article v-for="(item, key, index) of info">{{item}} {{key}} ...

  2. Spring Data JPA简单查询接口方法速查

    下表针对于简单查询,即JpaRepository接口(继承了CrudRepository接口.PagingAndSortingRepository接口)中的可访问方法进行整理.(1)先按照功能进行分类 ...

  3. delphi实现FTP上传与下载

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  4. js 输出语句document.write()及动态改变元素中内容innerHTML的使用

    操作 HTML 元素 如需从 JavaScript 访问某个 HTML 元素,您可以使用 document.getElementById(id) 方法. 请使用 "id" 属性来标 ...

  5. mysql脚本文件

    DELIMITER $$ -- USE `dev_seal_chip_sell_ms_v1`$$; DROP FUNCTION IF EXISTS `GET_ORDER_STATUS`$$ CREAT ...

  6. PAT Advanced 1020 Tree Traversals (25) [⼆叉树的遍历,后序中序转层序]

    题目 Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder an ...

  7. DRF框架之ModelSerializer序列化器

    ModelSerializer是Serializer的子类,序列化和反序列化跟Serializer一样. ModelSerializer与常规的Serializer相同,但提供了: 基于模型类自动生成 ...

  8. 迅为iTOP-开发板-驱动-can和rfid配置

    在迅为开发板中,在 4412,4418 以及 6818 中,有的开发板默认配置 RFID,有的默认配 置 CAN 驱动(IMX6 默认都配置). 本文档介绍如何配置 CAN 和 RFID 的驱动. 截 ...

  9. 吴裕雄--天生自然 PYTHON3开发学习:CGI编程

    <Directory "/var/www/cgi-bin"> AllowOverride None Options +ExecCGI Order allow,deny ...

  10. 联想的amd电脑,Debian8.8开机后亮度值始终最大,尝试过各种方法,始终无法解决,最后debian8.8在安装开源驱动后,成功调节

    安装ATI显卡驱动(开源)(方法步骤来自Debian WiKi) A.先升级可用的包 # aptitude upgrade B.安装下面3个包 # apt-get install firmware-l ...