spring顾问包装通知
前边说到了顾问就是通知,没有实践,这里就实践一下,证明一下。
虽然可以说顾问就是通知,但是他们还是有的一定的区别的,通知是将目标类中所有的方法都进行的增强,而顾问却可以指定到特定的方法上,也就是说顾问的功能更加强大一些
而包装的方式常用的有两种,一种是基于名字的(方法),一种是基于正则的(方法),他们都是通过目标类的方法名进行的包装。
创建增强类
/**
* 增强类
*/
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顾问包装通知的更多相关文章
- Spring——顾问封装通知
通知(advice)是Spring中的一种比较简单的切面,只能将切面织入到目标类的所有方法中,而无法对指定方法进行增强 顾问(advisor)是Spring提供的另外一种切面,可以织入到指定的方法中 ...
- Spring顾问、IOC注解和注解增强
一.顾问 通知的一种表现方式(顾问包装通知/增强) Advisor: 名称匹配方法: NameMecthMethodPointcutAdvisor 1.定义了一个业务类 package cn.spri ...
- Spring中的通知(Advice)和顾问(Advisor)
在Spring中,目前我学习了几种增强的方式,和大家分享一下 之前的话: 1.AOP (Aspect Oriented Programming 面向切面编程) 在软件业,AOP为Aspect O ...
- Spring笔记07(Spring AOP的通知advice和顾问advisor)
1.Spring AOP的通知advice 01.接口代码: package cn.pb.dao; public interface UserDao { //主业务 String add(); //主 ...
- spring aop 环绕通知around和其他通知的区别
前言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只 ...
- Spring AOP 四大通知
Spring AOP 四大通知 Spring 3.X 以前 1.前置通知,实现 MethodBeforeAdvice 接口,重写 public void before(Method metho ...
- [转载] spring aop 环绕通知around和其他通知的区别
前言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别: 1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只 ...
- spring aop环绕通知
[Spring实战]—— 9 AOP环绕通知 假如有这么一个场景,需要统计某个方法执行的时间,如何做呢? 典型的会想到在方法执行前记录时间,方法执行后再次记录,得出运行的时间. 如果采用Sprin ...
- Spring AOP--返回通知,异常通知和环绕通知
在上篇文章中学习了Spring AOP,并学习了前置通知和后置通知.地址为:http://www.cnblogs.com/dreamfree/p/4095858.html 在本文中,将继续上篇的学习, ...
随机推荐
- HDU-2544 最短路 Dijkstra模板题
题目链接:https://vjudge.net/problem/HDU-2544 题意: 题目要求找到节点1到节点n之间的一条最短路 分析: Dijkstra模板题 单源最短路径,可以用dijkstr ...
- CSS3-选中的锚链接改变指定样式
1.css样式 主角就是:target <a> 标签的 target 属性规定在何处打开链接文档,连接文档也可以是一个样式. 如果在一个 <a> 标签内包含一个 target ...
- vscode显示当前文件完整路径信息
Code->Preferences->Settings 搜索window.title 原本是activeEditorShort,修改 activeEditorShort => act ...
- Spring Cloud Alibaba 教程 | Nacos(五)
扩展配置(extended configurations) 通过之前的学习,我们知道应用引入nacos配置中心之后默认将会加载Data ID= ${prefix} - ${spring.profile ...
- 黑马程序员IDEA版JAVA基础班\JavaWeb部分视频\2-10Request和Response\第5节 request登录案例
用户登录案例需求: 1.编写login.html登录页面 username & password 两个输入框 2.使用Druid数据库连接池技术,操作mysql,day14数据库中user表 ...
- oracle 学习(五)pl/sql语言存储过程&包
首先搞清楚俩概念 存储过程(procedure)&程序包(package) 存储过程:数据库对象之一,可以理解为数据库的子程序,在客户端和服务器端可以直接调用它.触发器是与表直接关联的特殊存储 ...
- this, 闭包,箭头函数
闭包写法 //后台每个执行环境都有一个表示变量的对象---变量对象 //例如compare()函数调用 //compare的执行环境而言,其作用域链包含两个变量对象 本地活动对象 全局活动对象 全局变 ...
- Python—插入排序算法
# 插入排序,时间复杂度O(n²) def insert_sort(arr): """ 插入排序:以朴克牌为例,从小到大排序.摸到的牌current与手里的每张牌进行对比 ...
- Python opencv计算批量图片的BGR各自的均值
#coding:utf-8 #第一种方式 很慢很慢 自己写的如何计算均值 ''' import cv2 import os def access_pixels(frame): print(frame. ...
- 并发与高并发(二)-JAVA内存模型
一.java内存模型(JMM)-同步操作与规则 它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式.一个线程如何和何时能看到其他线程共享 ...