https://blog.csdn.net/yhl_jxy/article/details/80633194
一 CGLIB 介绍:
CGLIB(Code Generation Library)是一个开源项目!, 是一个强大的,高性能,高质量的code生成类库。
他可以在运行期扩展java类与实现java 接口,Hibernate用他来实现PO字节码的动态生成。
CGLIB是一个强大的高性能的代码生成包,他广泛的被许多AOP框架使用,例如
Spring Aop 为他们提供方法的interception(拦截)。cglib包的底层是通过使用一个小二块的字节码处理框架ASM,来转换字节码并生成新的类。
除了CGLIB包,脚本语言例如GROOVY和BeanShell,也是使用ASM来生成java的字节码。
二: CGLIB 动态代理实例:
1.pom
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
2, 实现一个业务类,注意这个业务类没有接口:
package com.taotao.bkpoxy.cglib;
/**
*@author tom
*Date 2020/7/6 0006 7:00
*实现一个业务类,没有实现任何接口
*/
public class HelloService {
public HelloService() {
System.out.println("HelloService构造");
}
/**
* 该方法不被子类覆盖,cglib是无法代理final 修饰方法的
* @param name
* @return
*/
final public String asyothers(String name){
System.out.println("Helloservice: sayothers>>"+name);
return null;
}
public void sayHello(){
System.out.println("HellowService: sayHello");
}
}
3,自定义MethodInterceptor
package com.taotao.bkpoxy.cglib;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
*@author tom
*Date 2020/7/6 0006 7:04
*
*/
public class MyMethodInterceptor implements MethodInterceptor {
/**
*
* @param o cglib 生成的代理对象
* @param method 被代理对象的方法
* @param objects 方法入参
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("========插入前置通知===========");
Object object=methodProxy.invokeSuper(o,objects);
System.out.println("=======插入后置通知====");
return object;
}
}
4,生成代理对象调用目标方法:
package com.taotao.bkpoxy.cglib;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;
/**
*@author tom
*Date 2020/7/6 0006 7:11
*生成CGLIB 代理类对象的方法
*/
public class Client {
public static void main(String[] args) {
//代理类class文件存入本地磁盘方便我们反编译查看源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:\\code");
//通过CGLIB动态代理获取代理对象的过程
Enhancer enhancer =new Enhancer();
//设置enhancer对象的父类
enhancer.setSuperclass(HelloService.class);
//设置enhancer的回调对象
enhancer.setCallback(new MyMethodInterceptor());
//创建代理对象
HelloService proxy=(HelloService)enhancer.create();
//通过代理对象调用目标方法
proxy.sayHello();
}
}
运行结果:
image.png
image.png
三 CGLIB动态代理源码分析
实现CGLIB动态代理必须实现MethodInterceptor(方法拦截器)接口,源码如下:
/*
* Copyright 2002,2003 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.cglib.proxy;
/**
* General-purpose {@link Enhancer} callback which provides for "around advice".
* @author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">baliuka@mwm.lt</a>
* @version $Id: MethodInterceptor.java,v 1.8 2004/06/24 21:15:20 herbyderby Exp $
*/
public interface MethodInterceptor
extends Callback
{
/**
* All generated proxied methods call this method instead of the original method.
* The original method may either be invoked by normal reflection using the Method object,
* or by using the MethodProxy (faster).
* @param obj "this", the enhanced object
* @param method intercepted Method
* @param args argument array; primitive types are wrapped
* @param proxy used to invoke super (non-intercepted method); may be called
* as many times as needed
* @throws Throwable any exception may be thrown; if so, super method will not be invoked
* @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
* @see MethodProxy
*/
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
MethodProxy proxy) throws Throwable;
}
这个接口只有一个intercept()方法,这个方法有4共 参数:
1,obj表示增强的对象,即实现这个接口类的一个对象:
2,method表示要拦截的方法:
3, args 表示要拦截方法的参数:
4,Proxy表示要触发父类的方法对象:
在上面的Client代码中,通过Enhancer.create()方法创建代理对象,create()方法的源码
/**
* Generate a new class if necessary and uses the specified
* callbacks (if any) to create a new object instance.
* Uses the no-arg constructor of the superclass.
* @return a new instance
*/
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
该方法的定义就是如果有必要就创建一个新类,并且使用指定的回调对象创建一个新的对象实例,使用的父类的参数的狗仔方法来实例化父类部分,核心内容在createHelper()中,源码如下:
private Object createHelper() {
preValidate();
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
preValidate()方法校验callbackTypes、filter是否为空,以及为空时的处理。
通过newInstance()方法创建EnhancerKey对象,作为Enhancer父类AbstractClassGenerator.create()方法
创建代理对象的参数。
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
真正创建代理对象方法在nextInstance()方法中,该方法为抽象类AbstractClassGenerator的一个方法,签名如下:
abstract protected Object nextInstance(Object instance) throws Exception;
在子类Enhancer中实现,实现源码如下:
protected Object nextInstance(Object instance) {
EnhancerFactoryData data = (EnhancerFactoryData) instance;
if (classOnly) {
return data.generatedClass;
}
Class[] argumentTypes = this.argumentTypes;
Object[] arguments = this.arguments;
if (argumentTypes == null) {
argumentTypes = Constants.EMPTY_CLASS_ARRAY;
arguments = null;
}
return data.newInstance(argumentTypes, arguments, callbacks);
}
看看data.newInstance(argumentTypes, arguments, callbacks)方法,
第一个参数为代理对象的构成器类型,第二个为代理对象构造方法参数,第三个为对应回调对象。
最后根据这些参数,通过反射生成代理对象,源码如下:
/**
* Creates proxy instance for given argument types, and assigns the callbacks.
* Ideally, for each proxy class, just one set of argument types should be used,
* otherwise it would have to spend time on constructor lookup.
* Technically, it is a re-implementation of {@link Enhancer#createUsingReflection(Class)},
* with "cache {@link #setThreadCallbacks} and {@link #primaryConstructor}"
*
* @see #createUsingReflection(Class)
* @param argumentTypes constructor argument types
* @param arguments constructor arguments
* @param callbacks callbacks to set for the new instance
* @return newly created proxy
*/
public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
setThreadCallbacks(callbacks);
try {
// Explicit reference equality is added here just in case Arrays.equals does not have one
if (primaryConstructorArgTypes == argumentTypes ||
Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
// If we have relevant Constructor instance at hand, just call it
// This skips "get constructors" machinery
return ReflectUtils.newInstance(primaryConstructor, arguments);
}
// Take a slow path if observing unexpected argument types
return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
} finally {
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(null);
}
}
代理对象继承于HelloService,拦截器调用intercept()方法,
intercept()方法由自定义MyMethodInterceptor实现,所以,最后调用MyMethodInterceptor中
的intercept()方法,从而完成了由代理对象访问到目标对象的动态代理实现。
网友评论