Spring AOP拦截-三种方式实现自动代理详解
这里的自动代理,我讲的是自动代理bean对象,其实就是在xml中让我们不用配置代理工厂,也就是不用配置class为org.springframework.aop.framework.proxyfactorybean的bean。
总结了一下自己目前所学的知识。
发现有三种方式实现自动代理
用spring一个自动代理类defaultadvisorautoproxycreator:
<bean class="org.springframework.aop.framework.autoproxy.defaultadvisorautoproxycreator" data-filtered="filtered"></bean>
例如:
原来不用自动代理的配置文件如下:
<!--?xml version="1.0" encoding="utf-8"?--> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:context="https://www.springframework.org/schema/context" xmlns:tx="https://www.springframework.org/schema/tx" xmlns:xsi="https://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.3.xsd https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.3.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- 代理前原对象 --> <bean class="cn.hncu.xmlimpl.person" id="person"></bean> <!-- 切面 = 切点+通知 --> <bean class="org.springframework.aop.support.regexpmethodpointcutadvisor" id="advisor"> <!-- 切点 --> <property name="patterns"> <list> <value>.*run.*</value> </list> </property> <!-- 通知-由我们写,实际代理动作 --> <property name="advice"> <bean class="cn.hncu.xmlimpl.aroundadvice" id="advice"></bean> </property> </bean> <!-- 代理工厂 --> <bean class="org.springframework.aop.framework.proxyfactorybean" id="personproxied"> <!-- 放入原型对象 --> <property name="target" ref="person"></property> <!-- 放入切面 --> <property name="interceptornames"> <list> <value>advisor</value> </list> </property> </bean> </beans>
现在改用自动代理,如下配置:
<beans ...=""> <!-- 代理前原对象 --> <bean class="cn.hncu.xmlimpl.person" id="person"></bean> <!-- 切面 = 切点+通知 --> <bean class="org.springframework.aop.support.regexpmethodpointcutadvisor" id="advisor"> <!-- 切点 --> <property name="patterns"> <list> <value>.*run.*</value> </list> </property> <!-- 通知-由我们写,实际代理动作 --> <property name="advice"> <bean class="cn.hncu.xmlimpl.aroundadvice" id="advice"></bean> </property> </bean> <!-- 自动代理 --> <bean class="org.springframework.aop.framework.autoproxy.defaultadvisorautoproxycreator"></bean> </beans>
测试方法
@test//自动代理 public void demo4(){ applicationcontext ctx = new classpathxmlapplicationcontext("cn/hncu/xmlimpl/4.xml"); //我们直接在这里获取person对象就可以了,因为在最开始xml文件newperson对象后,spring就已经帮我们代理了! person p =ctx.getbean(person.class); p.run(); p.say(); }
相对于前面,也就是把代理工厂部分换成自动代理了。
演示结果:
自己写一个自动代理底层实现:
我们也可以写一个类,来实现defaultadvisorautoproxycreator自动代理的功能!
首先,我们需要实现一个接口,也就是beanpostprocessor接口。
beanpostprocessor接口作用是:如果我们需要在spring容器完成bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个beanpostprocessor接口的实现,然后注册到容器中。
而我们想要在原型对象bean被创建之后就代理了,就必须在原来的容器中拿到原来的原型对象,需要拿到原来spring容器中的切面对象,这个时候,我们就需要原来的容器,这个时候就需要另一个接口,也就是applicationcontextaware接口!
通过这2个接口,我们就可以实现自动代理了。
package cn.hncu.xmlimpl; import org.springframework.aop.advisor; import org.springframework.aop.framework.proxyfactorybean; import org.springframework.beans.beansexception; import org.springframework.beans.factory.config.beanpostprocessor; import org.springframework.context.applicationcontext; import org.springframework.context.applicationcontextaware; public class myautoproxy implements beanpostprocessor,applicationcontextaware{ private applicationcontext applicationcontext=null; //bean创建之前调用 @override public object postprocessbeforeinitialization(object bean, string beanname) throws beansexception { return bean;//在这里,我们直接放行 } //bean创建之后调用 @override public object postprocessafterinitialization(object bean, string beanname) throws beansexception { proxyfactorybean factory = new proxyfactorybean(); //把原型对象放入代理工厂 factory.settarget(bean); //在这里 advisor adv = applicationcontext.getbean(advisor.class); factory.addadvisor(adv); //返回被代理后的对象 return factory.getobject(); } //拿到原来的spring中的容器 @override public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception { this.applicationcontext=applicationcontext; } }
5.xml
<beans...> <!-- 代理前原对象 --> <bean class="cn.hncu.xmlimpl.person" id="person"></bean> <!-- 切面 = 切点+通知 --> <bean class="org.springframework.aop.support.regexpmethodpointcutadvisor" id="advisor"> <!-- 切点 --> <property name="patterns"> <list> <value>.*run.*</value> </list> </property> <!-- 通知-由我们写,实际代理动作 --> <property name="advice"> <bean class="cn.hncu.xmlimpl.aroundadvice" id="advice"></bean> </property> </bean> <!-- 自己写的自动代理 --> <bean class="cn.hncu.xmlimpl.myautoproxy"></bean> </beans...>
测试方法:
@test//自己实现的自动代理 public void demo5(){ applicationcontext ctx = new classpathxmlapplicationcontext("cn/hncu/xmlimpl/5.xml"); person p =ctx.getbean(person.class); p.run(); p.say(); }
测试结果就不上图了,和前面是一样的。
其实很多时候,我们如果自己去练一下底层,对上层的框架更好理解。
还有一种方法。
使用aop标签配自动代理
需要在beans加一个命名空间
xmlns:aop=https://www.springframework.org/schema/aop
还需要配xsi:schemalocation,为aop加一个网络地址。
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.3.xsd
我们需要一个aspectjweaver-jar包:
xml配置文件:
<!--?xml version="1.0" encoding="utf-8"?--> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:aop="https://www.springframework.org/schema/aop" xmlns:context="https://www.springframework.org/schema/context" xmlns:tx="https://www.springframework.org/schema/tx" xmlns:xsi="https://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.3.xsd https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-4.3.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.3.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.3.xsd "> <!-- 利用sop标签实现自动代理 --> </aop:aspectj-autoproxy> <!-- 代理前原对象 --> <bean class="cn.hncu.xmlimpl.person" id="person"></bean> <!-- 切面 = 切点+通知 --> <bean class="org.springframework.aop.support.regexpmethodpointcutadvisor" id="advisor"> <!-- 切点 --> <property name="patterns"> <list> <value>.*run.*</value> </list> </property> <!-- 通知-由我们写,实际代理动作 --> <property name="advice"> <bean class="cn.hncu.xmlimpl.aroundadvice" id="advice"></bean> </property> </bean> </beans>
测试方法:
@test//自动代理 public void demo6(){ applicationcontext ctx = new classpathxmlapplicationcontext("cn/hncu/xmlimpl/6.xml"); person p =ctx.getbean(person.class); p.run(); p.say(); }
测试结果:
个人觉得能学会使用一种就ok了,不用全部记下来,为了学习,都了解一下就好,别人写出来,能看懂就好。
哈哈,其实底层学好了,自己写的时候,就算不会用spring的自动代理,自己写出来底层也是蛮好的嘛
总结
以上本文关于spring aop拦截-三种方式实现自动代理详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:快速理解java设计模式中的组合模式、java编程接口调用的作用及代码分享、浅谈java实体对象的三种状态以及转换关系等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!