spring8——AOP之Bean的自动代理生成器

  对于上篇博客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"/>

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

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

时间: 2024-10-05 21:06:57

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

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

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 名称自动代理生成器:BeanNameAutoProxyCreator 为了更好的测试,我放了俩个接口,俩个实现类: ISomeService接口: package cn.dawn.day18auto02; /** * Created by Dawn on 2018/3/8. */ public interface ISomeService { public void insert(); public voi

自动代理生成器

public interface ISomeService { public void doSome(); public void doSecont(); } 类 public class MyAfterReturningAdvice implements AfterReturningAdvice { public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable

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

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 默认自动代理DefaultAdvisorAutoProxyCreator 本处没有什么要讲的,放原代码 ISomeService接口: package cn.dawn.day17atuo01; /** * Created by Dawn on 2018/3/8. */ public interface ISomeService { public void insert(); public void dele

Spring Framework之Bean的自动装配检测和AOP简述

注解可以充分利用Java的反射机制获取类结构信息,从而有效减少配置工作:注解与java代码位于同一个文件,便于对变动的统一维护: 1)      Spring容器默认禁用注解装配,因此使用注解装配之前需要在配置文件中显示打开注解装配: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"

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

三.自动代理的实现 1.使用BeanNameAutoProxyCreator 通过Bean的name属性自动生成代理Bean. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Target</value>

spring(AOP,基于代理AOP实现,自动代理AOP实现,基于AspectJAOP[注解]实现)

----------------AOP------------------ ----------------------基于代理的AOP实现------------------------------------- 1.创建接口类,实现类 2.引入spring支持,勾选AOP支持 3.创建实现类的bean,代理类的bean 4.创建代理类并实现一下两个接口 5.定义切入点 6.定义通知(绑定一个代理),advice--->代理类,pointcut----->切入点 7.定义代理工厂 targe

Spring AOP自动代理创建者

1. BeanNameAutoProxyCreator示例 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springfra

spring aop自动代理xml配置

<?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:aop="http://www.springframework.org/schema/

Spring(十一)--代理生成器

Spring代理生成器 1.创建需要的dao接口 2.创建需要的daoImpl实现类 3.创建前置增强类 4.创建spring.xml文件 <!-- 这个案例 需要解决的问题: 一个代理工厂 配置 多个目标对象!--> <!--01.配置目标对象--> <bean id="userDao" class="com.xdf.dao.UserDaoImpl"/> <!--为了 测试 会给 所有的bean注入增强--> <