这篇文章紧接着上一篇静态代理和动态代理来说
前言:
到现在呢,老是讲动态代理,有的人都晕了,会说你这代理中用到的类怎么没有一个是与spring相关的呢,所以,我要说明的事,虽然现在讲的都是最普通的动态代理,但实质上就是将AOP的内部实现原理,Spring AOP之所以这么强大是因为它底层都是用动态代理来实现的,为了说明这一点,得贴出点源码来
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理
在spring的资源包中,找到org.springframework.aop.framework.JdkDynamicAopProxy这个类,在资源包的位置为spring-framework-2.5.6\src\org\springframework\aop\framework\JdkDynamicAopProxy.java,看看其中重要的代码片段
- <span style="font-size: medium;"> public Object getProxy(ClassLoader classLoader) {
- if (logger.isDebugEnabled()) {
- Class targetClass = this.advised.getTargetSource().getTargetClass();
- logger.debug("Creating JDK dynamic proxy" +
- (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
- }
- Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
- return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
- } </span>
再看org.springframework.aop.framework.ReflectiveMethodInvocation中的代码片段
- <span style="font-size: medium;">public Object proceed() throws Throwable {
- // We start with an index of -1 and increment early.
- if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
- return invokeJoinpoint();
- }
- Object interceptorOrInterceptionAdvice =
- this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
- if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
- // Evaluate dynamic method matcher here: static part will already have
- // been evaluated and found to match.
- InterceptorAndDynamicMethodMatcher dm =
- (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
- if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
- return dm.interceptor.invoke(this);
- }
- else {
- // Dynamic matching failed.
- // Skip this interceptor and invoke the next in the chain.
- return proceed();
- }
- }
- else {
- // It's an interceptor, so we just invoke it: The pointcut will have
- // been evaluated statically before this object was constructed.
- return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
- }
- }
- </span>
2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现
- <span style="font-size: medium;">private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {
- private final Object target;
- public StaticUnadvisedInterceptor(Object target) {
- this.target = target;
- }
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy methodProxy) throws Throwable {
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- }
- /**
- * Method interceptor used for static targets with no advice chain, when the
- * proxy is to be exposed.
- */
- private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
- private final Object target;
- public StaticUnadvisedExposedInterceptor(Object target) {
- this.target = target;
- }
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object oldProxy = null;
- try {
- oldProxy = AopContext.setCurrentProxy(proxy);
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
- /**
- * Interceptor used to invoke a dynamic target without creating a method
- * invocation or evaluating an advice chain. (We know there was no advice
- * for this method.)
- */
- private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object target = advised.getTargetSource().getTarget();
- try {
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- advised.getTargetSource().releaseTarget(target);
- }
- }
- }
- /**
- * Interceptor for unadvised dynamic targets when the proxy needs exposing.
- */
- private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object oldProxy = null;
- Object target = advised.getTargetSource().getTarget();
- try {
- oldProxy = AopContext.setCurrentProxy(proxy);
- Object retVal = methodProxy.invoke(target, args);
- return massageReturnTypeIfNecessary(proxy, target, retVal);
- }
- finally {
- AopContext.setCurrentProxy(oldProxy);
- advised.getTargetSource().releaseTarget(target);
- }
- }
- }</span>
好了,已经知道spring内部实现就是动态代理机制了,所以现在我们手动写的关于CGLIB的动态代理还是要写个小示例的。
上一篇文章中如果ServiceImpl没有实现任何接口的话,那么创建代理对象就不能使用javax.lang.Proxy这个类了,这时需要使用CGLIB了,在spring资源包中找到CGLIB的jar:spring-framework-2.5.6\lib\cglib\cglib-nodep-2.1_3.jar
然后写一个新的代理实现类CGlibProxyFactory.java
- <span style="font-size: medium;">package com.javacrazyer.dao;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class CGlibProxyFactory implements MethodInterceptor {
- private Object targetObject;
- public Object newProxy(Object targetObject) {
- this.targetObject = targetObject;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.targetObject.getClass());
- enhancer.setCallback(this);
- // 返回代理对象
- return enhancer.create();
- }
- /**
- * proxy 带来对象本身 method 被拦截到的方法 args 方法的参数 methodProxy 方法的代理对象
- */
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy methodProxy) throws Throwable {
- checkSecurity();
- Object ret = null;
- try {
- // 调用目标对象的真实方法
- ret = method.invoke(this.targetObject, args);
- // ret接受存在的返回值,不存在返回值则为Null
- } catch (Exception e) {
- e.printStackTrace();
- }
- return ret;
- }
- public void checkSecurity() {
- System.out.println("--------ServiceImpl.checkSecurity()----------");
- }
- }
- </span>
这时测试类有所变化
- <span style="font-size: medium;">package com.javacrazyer.dao;
- public class TestProxy {
- public static void main(String[] args) {
- CGlibProxyFactory hander = new CGlibProxyFactory();
- //创建代理对象,这是这个代理对象是UserManagerImpl的子类
- ServiceImpl service = (ServiceImpl)hander.newProxy(new ServiceImpl());
- service.outPut();
- service.putOut();
- }
- }
- </span>
输出结果
--------ServiceImpl.checkSecurity()----------
I am method outPut
--------ServiceImpl.checkSecurity()----------
I am method putOut
到目前位置,无论是前面的静态代理,javax.lang.Proxy的动态代理,还是这里的CGLIB的动态代理都是没有借助任何框架的情况下实现AOP的方法
相关推荐
Spring AOP通过代理模式实现这一目标,支持动态代理(基于JDK)和CGLIB代理(对于无接口的类)。 `spring-aop.xsd`包含了不同版本(2.5、3.1、3.2)的XML配置元素和属性定义,这意味着随着Spring框架的版本更新,...
1. **AOP代理**:Spring AOP支持两种代理方式,即JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于未实现接口的类。spring-aop.jar包含了这些代理机制的相关类,如`org.springframework.aop....
- **代理模式**:Spring AOP通过两种代理方式实现,即JDK动态代理和CGLIB代理。前者适用于接口实现类,后者适用于无接口的类。 - **注解驱动**:从4.0.0.RELEASE开始,Spring AOP支持完全基于注解的配置,大大...
3. **智能代理增强**:Spring AOP可以自动创建JDK动态代理或CGLIB代理,根据目标对象是否实现了接口来决定,这使得AOP能在各种情况下无缝工作。 4. **事务管理**:Spring AOP在事务管理方面有着出色的表现,可以...
总的来说,`spring-cglib-repack-3.2.0.jar`和`spring-objenesis-repack-2.1.jar`是Spring框架正常运行的关键组成部分,它们分别负责动态子类生成和无参构造函数对象的快速实例化,对于理解和优化Spring应用的性能有...
"spring-cglib-repack-3.2.5.jar"、"spring-objenesis-repack-2.6.jar"和"spring-objenesis-repack-2.5.1.jar"这三个文件是Spring源码阅读环境中常用的依赖包,它们各自承担着不同的功能。 首先,我们来看"CGLIB"...
标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是Spring框架在运行时依赖的两个关键库,它们主要涉及到动态代理和对象创建的优化。 1. **CGLIB(Code Generation Library)**: ...
在提供的文件中,我们看到了两个与Spring相关的库:`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`。这两个库都是Spring框架的重要组成部分,用于解决特定的编程问题。 首先,让我们来了解...
总的来说,`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`是Spring框架的核心组成部分,它们提供了代理和对象实例化的底层支持。在进行Spring源码学习或开发时,确保这两个库的正确引入是至...
默认情况下,Spring使用基于Java的代理,但对于需要在静态方法或非Spring管理对象上应用AOP的情况,可能需要使用CGLIB或AspectJ字节码代理。 5. **理解代理行为**:理解Spring AOP代理的工作方式很重要,因为这可能...
Spring-asm-repack和Spring-cglib-repack是Spring框架为了实现动态代理和增强类功能所使用的库。 ASM是一个Java字节码操控和分析框架,它可以直接生成和修改类的字节码。在Spring中,ASM主要用于AOP(面向切面编程...
标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是两个与Spring框架相关的库文件,它们主要用于Spring框架的内部实现,尤其是针对Java对象的创建和代理机制。下面将详细解释这两个库的...
com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aspects-4.1.2.RELEASE.jar spring-web-4.1.2.RELEASE.jar /...
在实际开发中,`spring-cglib-repack-3.2.4.jar`和`spring-objenesis-repack-2.5.1.jar`是Spring框架运行的必要组件,特别是对于那些使用AOP特性的项目。确保这两个jar包的正确引入,能有效避免因缺少依赖而导致的...
在Spring框架中,AOP通过代理模式实现,可以是JDK动态代理或者CGLIB代理。 首先,我们需要理解AOP的基本概念。切面(Aspect)是包含关注点的模块化单元,它封装了跨越多个对象的行为或责任。通知(Advice)是切面在...
5. **配置代理**:Spring会根据目标对象是否实现了接口来决定使用JDK动态代理还是CGLIB代理。如果目标对象实现了接口,Spring会选择JDK动态代理。动态代理类会继承自`java.lang.reflect.Proxy`,并实现目标对象的...
Spring支持两种类型的代理:JDK动态代理和CGLIB代理。JDK代理用于实现接口的对象,而CGLIB代理则用于不实现接口的类。ProxyFactoryBean是Spring AOP用于创建代理对象的主要工具,它实现了BeanFactoryAware、...
Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...
2. **org.springframework.aop.framework**:这个包包含了AOP的代理实现,包括JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于没有实现接口但需要进行AOP处理的类。Spring会根据目标对象是否...