• Spring -- 4.1


    CGLib动态代理

    使用JDK动态代理有一个限制,即它只能为接口创建代理实例,这一点可以从接口的newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)的第二个参数看出,interfaces就是需要代理实例实现的接口。对于没有通过接口定义的类,用CGLib技术动态创建代理实例。

    用一句简单的话说明这俩的区别:JDK生成的代理类和代理对象实现了同一个接口,CGLib生成的代理类是原代理对象的一个子类(所以被代理的类不能是final的,final不能有子类)。

    对于SpringAOP的理解,我们还是要从基本的定义开始:SpringAOP通过Pointcut(切点)指定哪些类的哪些方法上织入横切逻辑,通过Advice(增强)描述横切逻辑和方法的具体切入点(方法前、方法后、方法两端)。Spring通过Advisor(切面)将Pointcut和Advice两者组装起来(再次印证切面就是切点+横切逻辑)。有了Advisor的信息,Spring就可以利用JDK和CGLib的动态代理技术采用统一的方式为目标Bean创建代理对象了。

    增强的类型:前置增强、后置增强、环绕增强、异常抛出增强、引介增强。

    前置增强的一个例子(一个手写实现接口,一个通过Spring的配置文件):

    写一个接口和实现类:

     1 //服务员接口
     2 package module2.service;
     3 
     4 public interface Waiter {
     5     
     6     public void greetTo(String name);
     7     
     8     public void serveTo(String name);
     9 
    10 }
    11 //餐馆服务员接口
    12 package module2.service.Impl;
    13 
    14 import module2.service.Waiter;
    15 
    16 public class RestWaiter implements Waiter{
    17     
    18     public void greetTo(String name){
    19         System.out.println("---greet to "+name+"---");
    20     }
    21     
    22     public void serveTo(String name){
    23         System.out.println("---serving to "+name+"---");
    24     }
    25 
    26 }

    写一个增强(横切逻辑):

    //横切逻辑
    package module2.zq;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class GreetBeforeAdvice implements MethodBeforeAdvice {
        //实现接口的方法。
        public void before(Method method,Object[] args,Object obj) throws Throwable{
            //在目标方法调用前执行。
            String clientName = (String)args[0];
            System.out.println("---How are you ! Mr."+clientName+"---(横切逻辑)");
        }
    }

    测试代码和结果:

        public static void main(String[] args) {
            Waiter target = new RestWaiter();//目标对象。
            BeforeAdvice advice = new GreetBeforeAdvice();//增强(横切逻辑)。
            
            //Spring提供的代理工厂
            ProxyFactory pf = new ProxyFactory();
            //设置代理目标
            pf.setTarget(target);
            //为代理目标添加增强
            pf.addAdvice(advice);
            
            //生成代理实例
            Waiter proxyWaiter = (Waiter)pf.getProxy();
            proxyWaiter.greetTo("abao");
            proxyWaiter.serveTo("binge");
        }
    ==========================================
    ---How are you ! Mr.abao---(横切逻辑)
    ---greet to abao---
    ---How are you ! Mr.binge---(横切逻辑)
    ---serving to binge---

    在Spring配置中实现上面例子中的代理。

    配置文件:

          <bean id="greetAdvice" class="module2.zq.GreetBeforeAdvice"/> 
          <bean id="target" class="module2.service.Impl.RestWaiter"/>
          
          <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
             p:proxyInterfaces="module2.service.Waiter"
             p:interceptorNames="greetAdvice"
             p:target-ref="target"
          />

    测试代码:

    String configPath = "beans.xml";
    ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); 
    Waiter waiter = (Waiter)ctx.getBean("waiter");
    waiter.greetTo("bingee");

    代码看着很简单,但是大道至简,那些复杂的功能和抽象的概念都始于此!

  • 相关阅读:
    面试题目-atof与ftoa
    数据结构-List
    数据结构-Vector
    面试题目-计算最大公约数
    数据结构-二分查找
    面试题目-用递归通过单字符输出打印多位的数字
    Linux-守护进程的实现
    面试题目-链表反转
    Linux-C程序的存储空间布局
    Linux-如何添加路由表
  • 原文地址:https://www.cnblogs.com/lovery/p/3710622.html
Copyright © 2020-2023  润新知