对于上篇博客http://www.cnblogs.com/cdf-opensource-007/p/6464237.html结尾处提到的两个问题,可以使用spring提供的自动代理生成器解决。自动代理生成器可以让我们把切面织入目标对象方法时不用再使用ProxyFactoryBean这个类来生成代理对象了,同时可以把切面织入多个代理代理对象,并且在获取代理对象时使用的是目标对象的id来获取,这符合正常的使用习惯。

  spring提供了两个自动代理生成器,一个是DefaultAdvisorAutoProxyCreator,这一款代理生成器比较暴力,会把容器内所有的切面向所有的目标对象织入,而且切面只能是顾问的形式。另一款自动代理生成器是BeanNameAutoProxyCreator,这一款代码生成器就比较友好了,可以让我们有选择性的对目标对象和切面进行织入的操作,而且切面可以是顾问或者通知的形式。

下面我们还是以实验的形式说明问题。分别提供两个接口,和两个实现类,用于目标对象的创建,在上篇博客实验的基础上我们增加一个比较器的接口和实现类。

计算器接口:

public interface ICalculatorService {

    int add(int a,int b);

    int division(int a ,int b); 

}

比较器接口:

public interface IComparatorService {

    void comparator(int a,int b);
}

计算器实现类:

public class CalculatorServiceImpl implements ICalculatorService {

    @Override
public int add(int a, int b) {
return a+b;
} @Override
public int division(int a, int b) {
return a/b;
} }

比较器实现类:

public class ComparatorServiceImpl implements IComparatorService {

    @Override
public void comparator(int a, int b) { if(a > b){
System.out.println(a+"比"+b+"大");
}else if(a < b){
System.out.println(a+"比"+b+"小");
}else{
System.out.println(a+"等于"+b);
} } }

依旧提供三个切面的实现类,分别是前置通知,环绕通知和后置通知。

public class TestMethodBeforeAdive implements MethodBeforeAdvice {

    @Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行前置通知--->"+"正在执行的方法名为"+method.getName());
} }
public class TestMethodInterceptor implements MethodInterceptor {

    @Override
public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("执行环绕通知--->"+"正在执行的方法名为"+invocation.getMethod().getName()); Object[] arguments = invocation.getArguments();
int a = (int)arguments[0];
int b = (int)arguments[1];
if(b == 0){
System.err.println("除数不能为0");
return -1;
}
if(a == 0){
return 0;
} return invocation.proceed();
} }
public class TesAfterRunningAdive implements AfterReturningAdvice {

    @Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行后置通知--->"+"正在执行的方法名为"+method.getName());
} }

配置文件:

<?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"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 目标对象 -->
<bean id="comparatorServiceTarget" class="com.opensource.service.impl.ComparatorServiceImpl"/>
<bean id="calculatorServiceTarget" class="com.opensource.service.impl.CalculatorServiceImpl"/>
<!-- 通知 -->
<bean id="methodBeforeAdive" class="com.opensource.service.impl.TestMethodBeforeAdive"/>
<bean id="afterRunningAdive" class="com.opensource.service.impl.TesAfterRunningAdive"/>
<bean id="methodInterceptor" class="com.opensource.service.impl.TestMethodInterceptor"/>
<!-- 顾问 -->
<bean id="advisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="methodInterceptor"/>
<property name="mappedNames" value="division"/>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>calculatorServiceTarget</value>
<value>comparatorServiceTarget</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>methodBeforeAdive</value>
<value>afterRunningAdive</value>
<value>advisor</value>
</list>
</property>
</bean> </beans>

测试类:

public class MyTest {
public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring-bean.xml");
ICalculatorService bean = (ICalculatorService)ac.getBean("calculatorServiceTarget");
IComparatorService bean1 = (IComparatorService)ac.getBean("comparatorServiceTarget");
int division = bean.division(10, 0);
System.out.println("两数相除商为:"+division);
System.err.println("---------------------------------------------------------");
int add = bean.add(0, 2);
System.out.println("两数想加和为:"+add);
System.err.println("---------------------------------------------------------");
bean1.comparator(0, 1); } }

实验结果:

这里提一句:对于BeanNameAutoProxyCreator中beanNames和interceptorNames这两个属性可以采用模糊匹配的方式,例如以下这种形式:

<property name="beanNames" value="*Target"/>

还有对顾问包装通知时,一个顾问只能包装一个通知,这也体现了顾问对于通知的精细化管理。

  最后说一点,我们作为程序员,研究问题还是要仔细深入一点的。当你对原理了解的有够透彻,开发起来也就得心应手了,很多开发中的问题和疑惑也就迎刃而解了,而且在面对其他问题的时候也可做到触类旁通。当然在开发中没有太多的时间让你去研究原理,开发中要以实现功能为前提,可等项目上线的后,你有大把的时间或者空余的时间,你大可去刨根问底,深入的去研究一项技术,为觉得这对一名程序员的成长是很重要的事情。

spring8——AOP之Bean的自动代理生成器的更多相关文章

  1. SSM-Spring-15:Spring中名称自动代理生成器BeanNameAutoProxyCreator

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 名称自动代理生成器:BeanNameAutoProxyCreator 为了更好的测试,我放了俩个接口,俩个实现 ...

  2. Spring框架学习08——自动代理方式实现AOP

    在传统的基于代理类的AOP实现中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大.解决方案:自动创 ...

  3. Spring -- aop(面向切面编程),前置&后置&环绕&抛异常通知,引入通知,自动代理

    1.概要 aop:面向方面编程.不改变源代码,还为类增加新的功能.(代理) 切面:实现的交叉功能. 通知:切面的实际实现(通知要做什么,怎么做). 连接点:应用程序执行过程期间,可以插入切面的地点. ...

  4. SSM-Spring-14:Spring中默认自动代理DefaultAdvisorAutoProxyCreator

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 默认自动代理DefaultAdvisorAutoProxyCreator 本处没有什么要讲的,放原代码 ISo ...

  5. Spring 自动代理

    在传统的基于代理类的AOP实现中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大.解决方案:自动创 ...

  6. Spring AOP使用整理:自动代理以及AOP命令空间

    三.自动代理的实现 1.使用BeanNameAutoProxyCreator 通过Bean的name属性自动生成代理Bean. <bean class="org.springframe ...

  7. AOP的自动代理

    Spring的aop机制提供两类方式实现类代理.一种是单个代理,一种是自动代理. 单个代理通过ProxyFactoryBean来实现(就如上面的配置). 自动代理:自动代理能够让切面定义来决定那个be ...

  8. day39 07-Spring的AOP:自动代理

    带有切点的切面或者是不带有切点的切面配置一个类就要配置一段生成代理的代码,这样太麻烦了. 选中orderDao右键watch JDK动态代理是先创建被代理对象,然后在创建代理对象的时候传入被代理对象. ...

  9. 死磕Spring之AOP篇 - Spring AOP自动代理(一)入口

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

随机推荐

  1. templet模式

    package template;import java.sql.Connection;import java.sql.ResultSet;/** * Created by marcopan on 1 ...

  2. route路由的顺序问题了数据包的转发流程

    2018-02-28   15:29:26 [root@linux ~]# routeKernel IP routing tableDestination     Gateway           ...

  3. 关于Cesium中的常用坐标系及说明

    Cesium是一个基于JavaScript的开源框架,可用于在浏览器中绘制3D的地球,并在其上绘制地图(支持多种格式的瓦片服务),该框架不需要任何插件支持,但是浏览器必须支持WebGL. Cesium ...

  4. Ubuntu16.04 中 Vscode 如何断点调试C语言程序

    个人博客链接:Ubuntu16.04 中 Vscode 如何断点调试C语言程序 问题:环境是 Ubuntu16.04,如何使用 Vscode 断点调试C语言程序. 写代码没有调试环境是不能忍受的,所以 ...

  5. 关于Oracle-SQL语句性能优化

    Oracle-Sql语句性能优化 相信许多从事几年的开发人员都有过一些经验,相对于刚出来的毕业生而言,对于同种操作sql结果,他们的代码性能会更高一些.虽然本人还是个实习生,在这还是写写自己     ...

  6. IT连创业系列:产品设计之答题模块

    前言: 距上篇写完:IT连创业系列:新的一年,先淫文一篇! 转眼又两个星期了,今天不写文,估计大伙又得等两周了. 所以啊~~ 只能再努力一点了,花一天半天的,继续和大伙分享这让人心碎的创业历程. 这两 ...

  7. python之Redis的字符串类型操作

    redis的数据类型: 字符串型    哈希     列表     集合     有序集合 1.String(字符串类型) set  命令:   设置一个键和值,键存在则只覆盖,返回ok > s ...

  8. 【Python】 Web开发框架的基本概念与开发的准备工作

    Web框架基本概念 现在再来写这篇文章显然有些马后炮的意思.不过正是因为已经学习了Flask框架, 并且未来计划学习更加体系化的Django框架,在学习过程中碰到的很多术语等等,非常有必要通过这样一篇 ...

  9. zabbix自定义key监控memcache状态及其他服务进程

    一.在客户端 1.到/usr/loca/zabbix/conf/zabbix_agentd.conf里添加         UserParameter=memcached_stats[*],(echo ...

  10. 自己开发的 vue 滑动按钮组件 vue-better-slider

    写在前面的 这个人第一次尝试开发并发布一个 vue 的组件,该组件实现了类似 ios 手机淘宝客户端 -> 消息界面中消息的滑动删除功能等,如下为该组件的文档. 一个 Vue 的滑动按钮组件,有 ...