扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 BeanPostProcessor 来实现这项功能。
创新互联服务项目包括灵石网站建设、灵石网站制作、灵石网页制作以及灵石网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,灵石网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到灵石省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
1 BeanPostProcessor
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"?>
BeanNameAutoProxyCreator的 beanNames 属性允许指定一组需要自动代理的 Bean 名称, 这里可以使用 *
通配符 。
因为我们需要代理的类名分别是 user 与 charger,都是以 er 结尾的,所以我们这里定义为 *er
。
也可以通过 beanNames 的 value 值来明确指定需要代理的 Bean 名称,多个以逗号分隔(更常用)。
也可以通过 list 方式来指定 beanNames 的值:
user charger
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 中。
.*rent.*
首先我们配置了以静态正则表达式方法名匹配的切面,然后直接配置了 DefaultAdvisorAutoProxyCreator Bean。
测试代码与输出结果与上一小节的 BeanNameAutoProxyCreator 相同。
JDK 动态代理是通过接口来实现方法拦截,所以必须确保要拦截的目标在接口中有定义。
CGLib 动态代理是通过动态生成代理子类来实现方法拦截,所以必须确保要拦截的目标方法可以被子类所访问,也就是目标方法必须定义为非 final, 且非私有实例方法 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持创新互联。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流