Spring 中如何自动创建代理(spring中的三种自动代理创建器)
Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 BeanPostProcessor 来实现这项功能。
这三种自动代理创建器 为:BeanNameAutoProxyCreator , DefaultAdvisorAutoProxyCreator , AbstractAdvisorAutoProxyCreator。
1BeanPostProcessor
BeanPostProcessor 代理创建器的实现类可以分为 3 类:
类型 | 实现类 |
---|---|
基于 Bean 配置名规则 | BeanNameAutoProxyCreator |
基于 Advisor 匹配规则 | DefaultAdvisorAutoProxyCreator |
基于 Bean 中的 AspectJ 注解标签的匹配规则 | AnnotationAwareAspectJAutoProxyCreator |
BeanPostProcessor 类继承关系
所有的自动代理器类都实现了 BeanPostPorcessor ,在容器实例化 Bean 时, BeanPostProcessor 将对它进行加工处理,所以自动代理创建器能够对满足匹配规则的 bean 自动创建代理对象。
2 BeanNameAutoProxyCreator
假设有以下两个实体类(用户与充电宝)。
用户类:
public class User { public void rent(String userId) {
System.out.println("User:租赁【充电宝】");
} public void back(String userId){
System.out.println("User:归还【充电宝】"); }
}
充电宝:
public class Charger { public void rent(String userId) {
System.out.println("Charger:【充电宝】被租赁");
}
}
我们希望通过 BeanNameAutoProxyCreator 通过 Bean 的名称来自动创建代理,实现增强:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="user" class="net.deniro.spring4.aop.User"/>
<bean id="charger" class="net.deniro.spring4.aop.Charger"/> <!-- 前置增强-->
<bean id="rentBeforeAdvice" class="net.deniro.spring4.aop.RentBeforeAdvice"/> <!-- 使用 BeanNameAutoProxyCreator-->
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
p:beanNames="*er"
p:interceptorNames="rentBeforeAdvice"
p:optimize="true"
></bean>
</beans>
BeanNameAutoProxyCreator的 beanNames 属性允许指定一组需要自动代理的 Bean 名称, 这里可以使用 *
通配符 。
因为我们需要代理的类名分别是 user 与 charger,都是以 er 结尾的,所以我们这里定义为 *er
。
也可以通过 beanNames 的 value 值来明确指定需要代理的 Bean 名称,多个以逗号分隔(更常用)。
<!-- 指定自动代理的 Bean 名称-->
<property name="beanNames" value="user,charger">
</property>
也可以通过 list 方式来指定 beanNames 的值:
<property name="beanNames">
<list>
<value>user</value>
<value>charger</value>
</list>
</property>
p:optimize
设置为 true,则表示使用 CGLib 动态代理技术。
通过这样的配置之后,容器在创建 user 和 charger Bean 的实例时,就会自动为它们创建代理对象,而这一操作对于使用者来说完全是透明的 。
单元测试:
User user = (User) context.getBean("user");
Charger charger = (Charger) context.getBean("charger"); String userId = "001";
user.rent(userId);
charger.rent(userId);
输出结果:
准备租赁的用户 ID:001
User:租赁【充电宝】
准备租赁的用户 ID:001
Charger:【充电宝】被租赁
3 DefaultAdvisorAutoProxyCreator
切面 Advisor 是切点和增强的复合体,而 DefaultAdvisorAutoProxyCreator 能够扫描 Advisor, 并将 Advisor 自动织入到匹配的目标 Bean 中。
<bean id="user" class="net.deniro.spring4.aop.User"/>
<bean id="charger" class="net.deniro.spring4.aop.Charger"/> <!-- 前置增强-->
<bean id="rentBeforeAdvice" class="net.deniro.spring4.aop.RentBeforeAdvice"/> <!-- 静态正则表达式方法名匹配-->
<bean id="regexpAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:advice-ref="rentBeforeAdvice">
<!-- 匹配模式-->
<property name="patterns">
<list>
<!-- 匹配字符串-->
<value>.*rent.*</value>
</list>
</property>
</bean> <!-- 使用 DefaultAdvisorAutoProxyCreator-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
首先我们配置了以静态正则表达式方法名匹配的切面,然后直接配置了 DefaultAdvisorAutoProxyCreator Bean。
测试代码与输出结果与上一小节的 BeanNameAutoProxyCreator 相同。
JDK 动态代理是通过接口来实现方法拦截,所以必须确保要拦截的目标在接口中有定义。
CGLib 动态代理是通过动态生成代理子类来实现方法拦截,所以必须确保要拦截的目标方法可以被子类所访问,也就是目标方法必须定义为非 final, 且非私有实例方法 。
Spring 中如何自动创建代理(spring中的三种自动代理创建器)的更多相关文章
- 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件 内容简介:本文介绍 Spring Boot 的配置文件和配置管理,以及介绍了三种读取配置文 ...
- spring mvc从前台往后台传递参数的三种方式
jsp页面: 第一种:使用控制器方法形参的方式(常用) 第二种:使用模型传参的方式(如果前台往后台传递的参数非常多,如果还使用形参的方式传递,非常复杂.我们可以使用模型传参的方式,把多 个请求的参数 ...
- ARM微处理器中支持字节、半字、字三种数据类型,地址的低两位为0是啥意思?
问题: ARM微处理器中支持字节.半字.字三种数据类型,其中,字需要4字节对齐(地址的低两位为0).半字需要2字节对齐(地址的最低位为0).我想问的是括号中的内容是什么意思呢?请牛人帮忙解释一下!谢谢 ...
- Spring Boot将Mybatis返回结果转为驼峰的三种实现方式
本文不再更新,可能存在内容过时的情况,实时更新请访问原地址:Spring Boot将Mybatis返回结果转为驼峰的三种实现方式: 我们通常获取Mybatis返回的数据结果时想要将字段以驼峰的形式返回 ...
- spring mvc从后台往前台传参数的三种方式
第一种:使用Model对象(常用) 第一步:使用model对象往前台传递数据 第二步:在jsp中接收从后台传递过来的参数 第二种:使用HttpServletRequest对象 第一步:使用HttpSe ...
- CentOS7创建本地YUM源的三种方法
这篇文章主要介绍了CentOS7创建本地YUM源的三种方法,本文讲解了使用CentOS光盘作为本地yum源.如何为CentOS创建公共镜像.创建完全自定义的本地源等内容,需要的朋友可以参考下 ...
- Windows 10 应用创建模糊背景窗口的三种方法
原文 Windows 10 应用创建模糊背景窗口的三种方法 现代的操作系统中创建一张图片的高斯模糊效果非常容易,不过如果要在窗口中获得模糊支持就需要操作系统的原生支持了.iOS/Mac 和 Windo ...
- 02 Spring框架 简单配置和三种bean的创建方式
整理了一下之前学习Spring框架时候的一点笔记.如有错误欢迎指正,不喜勿喷. 上一节学习了如何搭建SpringIOC的环境,下一步我们就来讨论一下如何利用ioc来管理对象和维护对象关系. <? ...
- Spring创建对象的三种方式以及创建时间
创建对象的三种方式: 1.采用默认的构造函数创建 2.采用静态工厂方法 1.写一个静态工厂方法类 public class HelloWorldFactory { public static Hell ...
随机推荐
- Zookeeper集群快速搭建
Zookeeper集群快速搭建 1.cd /usr/local/zookeeper/conf(如在192.168.212.101服务器) mv zoo_sample.cfg zoo.cfg 修改con ...
- Linux系统层级结构标准
Linux Foundation有一套标准规范: FHS: Filesystem Hierarchy[‘haɪərɑːkɪ] Standard(文件系统层级标准)目前最新的标准是2.3版本:http: ...
- Mysql 查看连接数,状态及最大并发数(转载)
-- show variables like '%max_connections%'; 查看最大连接数 set global max_connections=1000 重新设置 mysql> ...
- sudo 不用输入密码
3. 设置当前登陆用户免密 使用visudo打开sudoers并编辑 sudo visudo 在刚才编辑的内容中加上NOPASSWD: linuxidc ALL=(ALL:ALL) NOPASSWD: ...
- mybatis 分页插件PageHelper的简单使用
首先在pom.xml配置文件中增加相关的插件. 插件地址:https://github.com/pagehelper/Mybatis-PageHelper <dependency> < ...
- 红帽Linux故障定位技术详解与实例(2)
红帽Linux故障定位技术详解与实例(2) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍 ...
- 求两个数的最大公约数和最小公倍数Java(cvte考题)
//最大公约数 最小公倍数 通过测试 public class GongYue{ public static int gongyue(int m, int n) throws Exception{ i ...
- Python 面向对象Ⅴ
基础重载方法 下表列出了一些通用的功能,你可以在自己的类重写: 运算符重载 Python同样支持运算符重载,实例如下: 以上代码执行结果如下所示: 类属性与方法 类的私有属性 __private_at ...
- json的值键对,对象,数组,逻辑值
详细说一下有关json的相关知识: ㈠json与xml的异同 ★与 XML 相同之处 ⑴JSON 是纯文本 ⑵JSON 具有"自我描述性"(人类可读) ⑶JSON 具有层级结构(值 ...
- Tomcat 激活spring profile
springboot打包war部署到外部tomcat的时候指定profile启动 windows 在%tomcat%/bin下创建setenv.bat文件 linux 在%tomcat%/bin下创建 ...