Background
About 'CGLIB', we can get information form
and in this article, we will use the asm framework, which website is:
http://asm.ow2.org/index.html
Introduction
This proxy is not same as JDK1.2+, which main through CGLIB to do this proxy, accurately, CGLIB use their proxy to realize the method interceptor at runtime, and which work with filter make it more flexible.
(Tip:About create proxy in runtime, we can use two different techniques, CGLIB or JDK dynamic proxies, more see:http://danni505.blog.51cto.com/15547/346896)
Base of the CGLIB, which can construct an AOP of CGLib-based AOP, which have support by spring framework.
Ok, now we have an four base opertaions for some datasource, but we need to control the delete operation just permit to daniel, and those base operations are some detail class, not show as interface, so what will you do if use proxy?
To solves the issue, here we use CGLIB proxy, the operation will contril by interceptor and the right person will control by filter, the code may be like this:
Source Code
package com.cglib;
/**
* Those are some base operation demo.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-08 11:25
*
*/
public class BaseOperations {
public void query() {
System.out.println("query");
}
public void create() {
System.out.println("create");
}
public void update() {
System.out.println("update");
}
public void delete() {
System.out.println("delete");
}
}
/**
* Those are some base operation demo.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-08 11:25
*
*/
public class BaseOperations {
public void query() {
System.out.println("query");
}
public void create() {
System.out.println("create");
}
public void update() {
System.out.println("update");
}
public void delete() {
System.out.println("delete");
}
}
/**
*
*/
package com.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* Method interceptor, as you see, this is a Interceptor, which can do some job before you call some method,
* and the key is which can be used in call back by cglib, it's real cool!
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:23
*
*/
public class MyMethodInterceptor implements MethodInterceptor{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyMethodInterceptor(String name) {
this.name = name;
}
/**
* Here we will set our interceptor for some method.
* As you see the interceptor is just for daniel by name.
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
//interceptor
if (this.name.equals("daniel")) {
return arg3.invokeSuper(arg0, arg2);
}else{
System.out.println("Method interceptor say: haha, just daniel can do delete! you are have no permits to do this operation!");
return null;
}
}
}
*
*/
package com.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* Method interceptor, as you see, this is a Interceptor, which can do some job before you call some method,
* and the key is which can be used in call back by cglib, it's real cool!
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:23
*
*/
public class MyMethodInterceptor implements MethodInterceptor{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyMethodInterceptor(String name) {
this.name = name;
}
/**
* Here we will set our interceptor for some method.
* As you see the interceptor is just for daniel by name.
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
//interceptor
if (this.name.equals("daniel")) {
return arg3.invokeSuper(arg0, arg2);
}else{
System.out.println("Method interceptor say: haha, just daniel can do delete! you are have no permits to do this operation!");
return null;
}
}
}
package com.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.CallbackFilter;
/**
* Interceptro filter, which mean this is a filter for interceptor, in other words, when app use the interceptor, filter
* will be called first, so it's can use for abstract the logic or bussiness into the filter, mean while you can
* set many interceptor and not case it use or not, the "CallBackFilter" will charge it, you just need to foucs
* at what will you do in filter.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 10:30
*
*/
public class InterceptorFilter implements CallbackFilter{
private String operationName;
@Override
public int accept(Method arg0) {
/*
* The accept logic
*/
if(arg0.getName().toString().equals(this.operationName)){
/*
* if the method name is equals to the filter's , call the No:0 interceptor
*/
return 0;
}else{
/*
* call No:1 interceptor
*/
return 1;
}
}
public InterceptorFilter(String name) {
this.operationName = name;
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.CallbackFilter;
/**
* Interceptro filter, which mean this is a filter for interceptor, in other words, when app use the interceptor, filter
* will be called first, so it's can use for abstract the logic or bussiness into the filter, mean while you can
* set many interceptor and not case it use or not, the "CallBackFilter" will charge it, you just need to foucs
* at what will you do in filter.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 10:30
*
*/
public class InterceptorFilter implements CallbackFilter{
private String operationName;
@Override
public int accept(Method arg0) {
/*
* The accept logic
*/
if(arg0.getName().toString().equals(this.operationName)){
/*
* if the method name is equals to the filter's , call the No:0 interceptor
*/
return 0;
}else{
/*
* call No:1 interceptor
*/
return 1;
}
}
public InterceptorFilter(String name) {
this.operationName = name;
}
}
package com.cglib;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;
/**
* This factory can set some interceptors into the callback of the class, not interface.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:25
*
*/
public class InterceptorFactory {
/**
* Here we will set the callback process by cglib's net.sf.cglib.proxy.Enhancer.
*
* @param interceptor
* @return BaseOperations
* @see net.sf.cglib.proxy.Enhancer
*/
public static BaseOperations getBtsOperationInstanceWithInterceptor(MyMethodInterceptor interceptor) {
/*
* This is a often and regular using of Enhancer.
*/
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BaseOperations.class);
/*
* setCallback just one interceptor
*/
enhancer.setCallback(interceptor);
/*
* set two interceptors into callback, which will used will see the filter's logic
*/
Callback[] backs = new Callback[]{interceptor,NoOp.INSTANCE};
enhancer.setCallbacks(backs);
//set filter
enhancer.setCallbackFilter(new InterceptorFilter("delete"));
BaseOperations baseOpt = (BaseOperations) enhancer.create();
return baseOpt;
}
/**
* Pay attention:
* Enhancer.setCallback and setCallbacks, by check the enhancer's source codethe, we find the setCallback
* will call setCallbacks() to set the same "Callback[]", so if you use the setCallBack before setCallBacks
* in reslut, the Callback[] will fit to the last one.
* Which Means, at here, ehancer have two interceptor in callback, not three!
*/
}
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;
/**
* This factory can set some interceptors into the callback of the class, not interface.
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:25
*
*/
public class InterceptorFactory {
/**
* Here we will set the callback process by cglib's net.sf.cglib.proxy.Enhancer.
*
* @param interceptor
* @return BaseOperations
* @see net.sf.cglib.proxy.Enhancer
*/
public static BaseOperations getBtsOperationInstanceWithInterceptor(MyMethodInterceptor interceptor) {
/*
* This is a often and regular using of Enhancer.
*/
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BaseOperations.class);
/*
* setCallback just one interceptor
*/
enhancer.setCallback(interceptor);
/*
* set two interceptors into callback, which will used will see the filter's logic
*/
Callback[] backs = new Callback[]{interceptor,NoOp.INSTANCE};
enhancer.setCallbacks(backs);
//set filter
enhancer.setCallbackFilter(new InterceptorFilter("delete"));
BaseOperations baseOpt = (BaseOperations) enhancer.create();
return baseOpt;
}
/**
* Pay attention:
* Enhancer.setCallback and setCallbacks, by check the enhancer's source codethe, we find the setCallback
* will call setCallbacks() to set the same "Callback[]", so if you use the setCallBack before setCallBacks
* in reslut, the Callback[] will fit to the last one.
* Which Means, at here, ehancer have two interceptor in callback, not three!
*/
}
/**
*
*/
package com.cglib;
/**
* In this case, we will do the job by cglib, we have set some method interceptor for our operations, let's take a look!
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:37
*
*/
public class CallInCase2 {
public static void main(String[] args) {
CallInCase2 c = new CallInCase2();
c.doOperation();
}
/**
* Do the base operations.
*/
private void doOperation() {
System.out.println( "app run:");
System.out.println( "============================ console outting: =========================");
//0.Create the interceptor
MyMethodInterceptor interceptor = new MyMethodInterceptor( "Tom"); //not ok
//1.Get handler by factory
BaseOperations basOptHandler = InterceptorFactory.getBtsOperationInstanceWithInterceptor(interceptor);
//2.Try do job
basOptHandler.create();
basOptHandler.query();
basOptHandler.update();
basOptHandler.delete();
//3.say BYEBYE
System.out.println( "============================ app stop =========================");
}
}
*
*/
package com.cglib;
/**
* In this case, we will do the job by cglib, we have set some method interceptor for our operations, let's take a look!
*
* @author daniel cqyd505@gmail.com
* @since 2010-07-09 09:37
*
*/
public class CallInCase2 {
public static void main(String[] args) {
CallInCase2 c = new CallInCase2();
c.doOperation();
}
/**
* Do the base operations.
*/
private void doOperation() {
System.out.println( "app run:");
System.out.println( "============================ console outting: =========================");
//0.Create the interceptor
MyMethodInterceptor interceptor = new MyMethodInterceptor( "Tom"); //not ok
//1.Get handler by factory
BaseOperations basOptHandler = InterceptorFactory.getBtsOperationInstanceWithInterceptor(interceptor);
//2.Try do job
basOptHandler.create();
basOptHandler.query();
basOptHandler.update();
basOptHandler.delete();
//3.say BYEBYE
System.out.println( "============================ app stop =========================");
}
}
End
In fact, we just have used Enhancer, Callback, MethodInterceptor and CallbackFilter of CGLIB, it realize a proxy solution for us, and it's also be used widespread in some common use framework, if you take care about it.
(Tip:CGLIB, which API and document is so simple that I could find more using about she, so if you have any good using case, pls msn me by danni-505@hotmail.com)
本文转自danni505 51CTO博客,原文链接:http://blog.51cto.com/danni505/346758
,如需转载请自行联系原作者