首页 > 代码库 > Spring -- 4.1

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");

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