Spring AOP 动态代理(二)

简介

Spring AOP 大家在使用Spring 框架 一定非常的熟悉

Spring AOP 的本质其实就是实现了动态代理,这个和Aspectj不一样,AspectJ 是直接修改你的字节码 完成的

代理模式其实很简单 主要包括 接口+真实的实现类+代理类 在真实类的实例化的时候 使用代理类,所以需要 Spring AOP 做的是生成一个代理类,然后替换真实的类 去对外提供服务

那怎么去替换呢?

就是Spring IOC 容器中获取Bean–getBean()的是时候IOC容器返回的时候 代理类的实例 而非真实类的实例,这个代理类 我们没有写任何的代码去实现,是通过java的动态代理或者CGLIB的代理去实现的

2种代理技术的对比

那为什有2中动态代理技术呢?是因为java的动态代理需要真实类实现一个接口,这就限制了我们的使用,而CGLIB 则不需要,一个普通的类和实现接口的类都是可以被代理的,Spring AOP中默认是用的Java的动态代理。

那Java的动态代理为什么有这个限制呢?是因为生成的代理类的父类是Proxy类 而Java中普通的类默认都是父类都是Object类的,但是Java 不允许多继承 所以只能代理实现接口的类

二者的比较

Java原生的API进行操作,在生成类上比较高效,CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

Java 动态代理

/**
 * @ClassName OrderService
 * @Auther burgxun
 * @Description: 订单服务接口
 * @Date 2020/4/22 1:33
 **/
public interface OrderService {
    void subOrder(User user);
}

/**
 * @ClassName OrderServiceImpl
 * @Auther burgxun
 * @Description: 订单服务接口的实现类
 * @Date 2020/4/23 0:47
 **/
public class OrderServiceImpl implements OrderService {
    @Override
    public void subOrder(User user) {
        System.out.println("执行下单逻辑,user:" + user.toString());
    }
}

/**
 * @ClassName OrderServiceInvocationHandler
 * @Auther burgxun
 * @Description:  JDK 实现的动态代理
 * @Date 2020/4/23 0:49
 **/
public class OrderServiceInvocationHandler implements InvocationHandler {

    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("===============方法调用前处理==========");
        result = method.invoke(target, args);
        //System.out.println(proxy);
        System.out.println("===============方法调用后处理==========");
        return result;
    }
}

CGLIB 动态代理

/**
 * @ClassName OrderServiceMethodIntercepter
 * @Auther burgxun
 * @Description: CGLIB 实现的动态代理
 * @Date 2020/4/27 16:21
 **/
public class OrderServiceMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("=====调用前处理=====" + method.getName());
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("=====调用后处理=====");
        return object;
    }
}

二者的使用

/**
 * @ClassName SpringProxyTest
 * @Auther burgxun
 * @Description:
 * @Date 2020/4/23 1:04
 **/
public class SpringProxyTest {
    public static void main(String[] args) {
        /*JDK 实现动态代理*/
        OrderServiceImpl serviceImpl = new OrderServiceImpl();
        OrderServiceInvocationHandler invocationHandler = new OrderServiceInvocationHandler();
        OrderService service = (OrderService) invocationHandler.bind(serviceImpl);
        service.subOrder(new User("fei", "yang"));

        /*CGLIB 实现的代理*/
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OrderServiceImpl.class);
        enhancer.setCallback(new OrderServiceMethodInterceptor());
        OrderServiceImpl serviceImplForCGLIB = (OrderServiceImpl) enhancer.create();
        serviceImplForCGLIB.subOrder(new User("burg", "xun"));
    }
}

执行的结果:

Java动态代理---方法调用前处理==========
执行下单逻辑,user:fei:yang-0
Java动态代理---方法调用后处理==========

CGLIB动态代理---调用前处理=====subOrder
执行下单逻辑,user:burg:xun-0
CGLIB动态代理---调用后处理=====

Spring 源码

  
    /** 
	* ProxyFactory 类中
	*/
    public class ProxyFactory extends ProxyCreatorSupport {
        /**
    	 * 返回代理一个代理
    	 */
    	public Object getProxy() {
    		return createAopProxy().getProxy();
    	} 
    }
 

createAopProxy()方式是在ProxyCreatorSupport的父类方法中,进入ProxyCreatorSupport中去看

   /** 
	* ProxyCreatorSupport 类中
	*/
	public class ProxyCreatorSupport extends AdvisedSupport {
	
	    private AopProxyFactory aopProxyFactory;
	    
	    /** 
    	* 默认的构造函数  aopProxyFactory 默认实现是DefaultAopProxyFactory
    	*/
	    public ProxyCreatorSupport() {
    		this.aopProxyFactory = new DefaultAopProxyFactory();
    	}
	    
	    
	    public AopProxyFactory getAopProxyFactory() {
	     	return this.aopProxyFactory;
     	}
	    
    	/**
    	 * 子类调用此方法 得到一个AopProxy的对象
    	 */
    	protected final synchronized AopProxy createAopProxy() {
    		if (!this.active) {
    			activate();
    		}
    		return getAopProxyFactory().createAopProxy(this);
    	}
	}

aopProxyFactory的默认实现是DefaultAopProxyFactory 所以createAopProxy也是调用此类的方法

    
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    
        @Override
    	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    	    <!--
    	    isOptimize和isProxyTargetClass默认是false 
    	    hasNoUserSuppliedProxyInterfaces的判断当前类是否有接口的实现
    	    -->
    		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    			Class<?> targetClass = config.getTargetClass();
    			if (targetClass == null) {
    				throw new AopConfigException("TargetSource cannot determine target class: " +
    						"Either an interface or a target is required for proxy creation.");
    			}
    			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    				return new JdkDynamicAopProxy(config);
    			}
    			return new ObjenesisCglibAopProxy(config);//CGLIB的动态代理
    		}
    		else {
    			return new JdkDynamicAopProxy(config);//JDK的动态代理
    		}
    	}
    	
    	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
    		Class<?>[] ifcs = config.getProxiedInterfaces();
    		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    	}
    }
    

上面就是AOP 在处理动态代理 代码 后面的源码 后面有时间在跟进去 分析一遍 ,时间限制 写的比较简单 后面会深入分析一下

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值