大家好,又见面了,我是你们的朋友全栈君。
一、CGlib简介
CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 当然这些实际的功能是asm所提供的,asm又是什么?Java字节码操控框架,具体是什么大家可以上网查一查,毕竟我们这里所要讨论的是cglib。cglib就是封装了asm,简化了asm的操作,实现了在运行期动态生成新的class。 可能大家还感觉不到它的强大,现在就告诉你。 实际上CGlib为spring aop提供了底层的一种实现;hibernate使用cglib动态生成VO/PO (接口层对象)。
二、CGlib之Enhancer和MethodInterceptor类
同时,Enhancer在生成一个类之前需要指定一个Callback,当类方法调用时,方法的执行被分配给这个Callback。
public interface MethodInterceptor extends Callback {
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
}
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
从参数构成上,methodInterceptor的输入参数比Invocationhandler多1个,其实前3个参数对象的含义与Invocationhandler的含义是相同的。
第一个参数表示调用方法来自哪个对象;
第二个参数表示调用方法的Method对象;
第三个参数表示此次调用的输入参数列表;
methodInterceptor多出来的参数是MethodProxy 类型的,它是cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升。
- 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 MyMethodInterceptor implements MethodInterceptor {
- // 接口1
- static interface Inter1{
- public void fun1();
- }
- // 接口2
- static interface Inter2{
- public String fun2(String arg0);
- }
- // 内部方法
- public String myFun1(String arg0){
- return “hello,” + arg0 ;
- }
- public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- String methodName = method.getName();
- if( “fun1” .equals(methodName) ){
- System. out .println( “[intercept] fun1 invoked” );
- return null;
- } else if ( “fun2” .equals(methodName) ){
- System. out .println( “[intercept] fun2 invoked before” );
- String result = (String)args[0] + “…” ;
- System. out .println( result );
- System. out .println( “[intercept] fun2 invoked after” );
- return result;
- } else if ( “myFun1” .equals(methodName) ){
- System. out .println( “[intercept] myFun1 invoked before” );
- Object result = proxy. invokeSuper(obj, args);
- System. out .println( result );
- System. out .println( “[intercept] myFun1 invoked after” );
- return result;
- }
- return null;
- }
- public Object createProxy(){
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(MyMethodInterceptor. class );
- enhancer.setInterfaces( new Class[]{Inter1. class,Inter2. class});
- enhancer.setCallback( this );
- return enhancer.create();
- }
- public static void main(String[] args) {
- MyMethodInterceptor ss = new MyMethodInterceptor();
- Object proxy = ss.createProxy();
- // 接口
- Inter1 inter1 = (Inter1)proxy;
- inter1.fun1();
- Inter2 inter2 = (Inter2)proxy;
- inter2.fun2( “code generate library” );
- // 类
- MyMethodInterceptor c1 = (MyMethodInterceptor)proxy;
- c1.myFun1( “cglib” );
- }
- }
[intercept] fun2 invoked before
code generate library…
[intercept] fun2 invoked after
[intercept] myFun1 invoked before
hello,cglib
[intercept] myFun1 invoked after
- public Object invoke (Object obj, Object[] args) throws Throwable
- public Object invokeSuper(Object obj, Object[] args) throws Throwable
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Callback;
- import net.sf.cglib.proxy.CallbackFilter;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class CallbackTest {
- public void fun1(){
- System. out .println( “fun1 invoekd” );
- }
- public void fun2(){
- System. out .println( “fun2 invoekd” );
- }
- static class ClassA implements MethodInterceptor{
- public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- System. out .println( “ClassA intercept invoked…” );
- return proxy.invokeSuper(obj, args);
- }
- }
- static class ClassB implements MethodInterceptor{
- public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- System. out .println( “ClassB intercept invoked…” );
- return proxy.invokeSuper(obj, args);
- }
- }
- public Object createProxy(){
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(getClass());
- enhancer.setCallbacks( new Callback[]{ new ClassA(), new ClassB() });
- enhancer.setCallbackFilter( new CallbackFilter() {
- public int accept(Method method) {
- String methodName = method.getName();
- if( “fun1” .equals(methodName) ){
- return 0;
- } else {
- return 1;
- }
- }
- });
- return enhancer.create();
- }
- public static void main(String[] args) {
- CallbackTest test = new CallbackTest();
- CallbackTest obj = (CallbackTest)test.createProxy();
- obj.fun1();
- obj.fun2();
- }
- }
输出结果:
fun1 invoekd
ClassB intercept invoked…
fun2 invoekd
- import net.sf.cglib.proxy.Mixin;
- public class MixinTest {
- static interface Inter1 {
- void fun1(String arg0);
- }
- static interface Inter2 {
- void fun1(String arg0);
- void fun2(int arg0);
- }
- public static void main(String[] args) {
- Mixin mixin = Mixin. create( new Class[]{Inter1. class ,Inter2.class },
- new Object[]{
- new Inter1() {
- public void fun1(String arg0) {
- System.out .println(“Inter1 – “ + arg0);
- }
- },
- new Inter2() {
- public void fun1(String arg0) {
- System.out .println(“Inter1 – “ + arg0);
- }
- public void fun2( int arg0) {
- System.out .println(“Inter2 – “ + arg0);
- }
- }
- });
- Inter1 inter1 = (Inter1) mixin;
- inter1.fun1( “hello” );
- Inter2 inter2 = (Inter2) mixin;
- inter2.fun1( “world” );
- inter2.fun2(999);
- }
- }
Inter1 – world
Inter2 – 999
生成的2个类是MixinTest$1.class和MixinTest$2.class,也就是说其实CGLIB没有为这2个代理对象生成1个类,而是生成了2个类,
反编译一下这2个类,我们可以看到生成的Mixin对象其实是引用了这两个类对象。
- class MixinTest$1 implements MixinTest.Inter1
- {
- public void fun1(String arg0)
- {
- System.out.println(“Inter1 – “ + arg0);
- }
- }
- class MixinTest$2
- implements MixinTest.Inter2
- {
- public void fun1(String arg0)
- {
- System.out.println(“Inter1 – “ + arg0);
- }
- public void fun2(int arg0) {
- System.out.println(“Inter2 – “ + arg0);
- }
- }
- import java.util.Arrays;
- import java.util.List;
- import net.sf.cglib.beans.BeanCopier;
- import org.apache.commons.lang.builder.ToStringBuilder;
- import org.apache.commons.lang.builder.ToStringStyle;
- public class BeanCopierTest {
- static class ClassA{
- private String username ;
- private String password ;
- private String score ;
- private List<String> list ;
- public String getUsername() {
- return username ;
- }
- public void setUsername(String username) {
- this .username = username;
- }
- public String getPassword() {
- return password ;
- }
- public void setPassword(String password) {
- this .password = password;
- }
- public String getScore() {
- return score ;
- }
- public void setScore(String score) {
- this .score = score;
- }
- public List<String> getList() {
- return list ;
- }
- public void setList(List<String> list) {
- this .list = list;
- }
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString( this , ToStringStyle.MULTI_LINE_STYLE );
- }
- }
- static class ClassB{
- private String username ;
- private String password ;
- private String address ;
- private List<Integer> list ;
- public String getUsername() {
- return username ;
- }
- public void setUsername(String username) {
- this .username = username;
- }
- public String getPassword() {
- return password ;
- }
- public void setPassword(String password) {
- this .password = password;
- }
- public String getAddress() {
- return address ;
- }
- public void setAddress(String address) {
- this .address = address;
- }
- public List<Integer> getList() {
- return list ;
- }
- public void setList(List<Integer> list) {
- this .list = list;
- }
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString( this , ToStringStyle.MULTI_LINE_STYLE );
- }
- }
- public static void main(String[] args) {
- BeanCopier beanCopier = BeanCopier.create(ClassA. class,ClassB. class ,false );
- List<String> list = Arrays. asList( new String[]{ “a” ,“b” ,“c” } );
- ClassA a = new ClassA();
- a.setUsername( “hello” );
- a.setPassword( “world” );
- a.setScore( “99” );
- a.setList(list);
- ClassB b = new ClassB();
- b.setUsername( “hello” );
- b.setPassword( “world” );
- b.setAddress( “beijing” );
- beanCopier.copy(a, b, null );
- System. out .println( a );
- System. out .println( b );
- }
- }
我们可以看到,对于2个对象中的同名属性 username 和 password进行了拷贝,并且对内部的符合属性List a 也进行了复制,但是,通过debug我们可以发现,内部的符合属性其实并没有实现copy。
因为他们在内存中实现上是同一个对象,对于内置复合对象的拷贝,需要寻找其他途径。而且,虽然ClassA中是List<String>,ClassB中是List<Integer>,在赋值的时候并没有抛出异常,也就是仅仅是内存上的赋值成功,并没有进行繁星检查,这也充分说明Java的泛型为伪泛型,在运行时会“泛型”会消失。但是如果此后在调用赋值之后的泛型不支持的方法时,就可能会遇到运行时异常。这会是一个安全隐患。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/137889.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...