详解在Spring中如何自动创建代理

2025-05-29 0 29

spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 beanpostprocessor 来实现这项功能。

1 beanpostprocessor

beanpostprocessor 代理创建器的实现类可以分为 3 类:

类型 实现类
基于 bean 配置名规则 beannameautoproxycreator
基于 advisor 匹配规则 defaultadvisorautoproxycreator
基于 bean 中的 aspectj 注解标签的匹配规则 annotationawareaspectjautoproxycreator

详解在Spring中如何自动创建代理

beanpostprocessor 类继承关系

所有的自动代理器类都实现了 beanpostporcessor ,在容器实例化 bean 时, beanpostprocessor 将对它进行加工处理,所以自动代理创建器能够对满足匹配规则的 bean 自动创建代理对象。

2 beannameautoproxycreator
假设有以下两个实体类(用户与充电宝)。

用户类:

?

1

2

3

4

5

6

7

8

9

10

11
public class user {

public void rent(string userid) {

system.out.println("user:租赁【充电宝】");

}

public void back(string userid){

system.out.println("user:归还【充电宝】");

}

}

充电宝:

?

1

2

3

4

5

6
public class charger {

public void rent(string userid) {

system.out.println("charger:【充电宝】被租赁");

}

}

我们希望通过 beannameautoproxycreator 通过 bean 的名称来自动创建代理,实现增强:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20
<?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 名称,多个以逗号分隔(更常用)。

?

1

2

3
<!-- 指定自动代理的 bean 名称-->

<property name="beannames" value="user,charger">

</property>

也可以通过 list 方式来指定 beannames 的值:

?

1

2

3

4

5

6
<property name="beannames">

<list>

<value>user</value>

<value>charger</value>

</list>

</property>

p:optimize 设置为 true,则表示使用 cglib 动态代理技术。

通过这样的配置之后,容器在创建 user 和 charger bean 的实例时,就会自动为它们创建代理对象,而这一操作对于使用者来说完全是透明的 。

单元测试:

?

1

2

3

4

5

6
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 中。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22
<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, 且非私有实例方法 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:https://www.jianshu.com/p/816078a79001

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 详解在Spring中如何自动创建代理 https://www.kuaiidc.com/111469.html

相关文章

发表评论
暂无评论