cglib动态代理
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
它只有两个核心API,MethodInterceptor.intercept拦截方法,Enhancer.create代理子类生成方法,所以不能代理final类。它速度快的原因是它内部维护了一套代理子类方法的索引表,寻址时会比较多。
public class Person {
public void testMethod(){
}
public static void main(String []args){ MethodInterceptor interceptor = new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("start"); Object proxy = methodProxy.invokeSuper(o, objects);//因为是创建子类的方式,所以此方法相当于调用了原方法 System.out.println("end"); return proxy; } }; Person person = (Person) Enhancer.create(Person.class, interceptor); person.testMethod(); } } |
简单的cglib示例-代理方法
public class ConcreteClassNoInterface {
public String methodA(String str){
System.out.println("methodA:"+ str);
return str;
}
}
/**调用目标方法时,CGLIB会回调MethodInterceptor接口方法拦截,来实现你自己的代量逻辑
* Created by liudong on 15/7/20.
*/
public class ConcreteClassInterceptor implements MethodInterceptor{
/**
*
* @param o cglib动态生成的代理类实现
* @param method 上文中实体类中被代理方法的引用
* @param arg 参数列表
* @param methodProxy 生成的代理方法的引用
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
System.out.println("before:"+ method);
Object obj = methodProxy.invokeSuper(o, arg);//调用的是被代理类的相应的方法
System.out.println("after:"+ method);
return obj;
}
public static void main(String []args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ConcreteClassNoInterface.class);
enhancer.setCallback(new ConcreteClassInterceptor());
ConcreteClassNoInterface ccni = (ConcreteClassNoInterface)enhancer.create();//动态生成代理类
ccni.methodA("ld");
}/*:)output
before:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
methodA:ld
after:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)*/
}
回调过滤器-回调过滤
在应用上述方法拦截后,可以对返回的结果进行二次过滤。
public class ConcreteClassNoInterface {
public String methodA(String str){
System.out.println("methodA:"+ str);
return str;
}
public int methodB(int n){
System.out.println("methodB:"+ n);
return n+10;
}
public int methodC(int n){
System.out.println("methodC:"+ n);
return n+10;
}
}
public class ConcreteClassFixedValue implements FixedValue {
@Override
public Object loadObject() throws Exception {
System.out.println("ConcreteClassFixedValue loadObject...");
Object object = 999;
return object;
}
}
public class ConcreteClassInterceptor implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
System.out.println("before:"+ method);
Object obj = methodProxy.invokeSuper(o, arg);//调用的是被代理类的相应的方法
System.out.println("after:"+ method);
return obj;
}
}
public class ConcreteClassCallbackFilter implements CallbackFilter {
@Override
public int accept(Method method) {
if ("methodA".equals(method.getName())){
return 0;//这个返回值对应main方法中callbacks数组的位置,调用方法时会用相应索引的拦截器拦截
}else if("methodB".equals(method.getName())){
return 1;
}else if("methodC".equals(method.getName())){
return 2;
}
return 1;
}
public static void main(String []args){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ConcreteClassNoInterface.class);
CallbackFilter filter = new ConcreteClassCallbackFilter();
enhancer.setCallbackFilter(filter);
Callback interceptor = new ConcreteClassInterceptor();
Callback noOp = NoOp.INSTANCE;//什么也不做,代理类直接调用被代代理的方法不进行拦截
Callback fixedValue = new ConcreteClassFixedValue();//锁定方法返回值而忽略被代理类的方法返回值
Callback[] callbacks = new Callback[]{interceptor, noOp, fixedValue};
enhancer.setCallbacks(callbacks);
ConcreteClassNoInterface ccni = (ConcreteClassNoInterface)enhancer.create();//动态生成代理类
System.out.println(ccni.methodA("ld")+"\n");
System.out.println(ccni.methodB(2)+"\n");
System.out.println(ccni.methodC(128));
}
}/*:)output
before:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
methodA:ld
after:public java.lang.String com.shiro.spring.cglib.ConcreteClassNoInterface.methodA(java.lang.String)
ld
methodB:2
12
ConcreteClassFixedValue loadObject...
999*/
延迟加载-LazyLoader接口
这引接口直接继承了Callback,也是callback类型中的一种。对需要延迟加载的对象添加代理,在获取该对象属性时先通过代理类回调方法进行对象初始化,在不需要加载该对象时,只要不去获取该对象内属性,该对象就不会被初始化了(在cglib中调用getter方法就会自动触发代理类回调)。
/**实体类
* Created by liudong on 15/7/20.
*/
public class LoaderBean {
private String loaderName;
private int loaderValue;
private PropertyBean propertyBean;//需要延迟加载的对象
public LoaderBean(){
this.loaderName = "loaderNameA";
this.loaderValue = 123;
this.propertyBean = createPropertyBean();//用ConcreteClassLazeLoader类完成代理类生成
}
protected PropertyBean createPropertyBean(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PropertyBean.class);
return (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassLazeLoader());
}
public String getLoaderName() {
return loaderName;
}
public void setLoaderName(String loaderName) {
this.loaderName = loaderName;
}
public int getLoaderValue() {
return loaderValue;
}
public void setLoaderValue(int loaderValue) {
this.loaderValue = loaderValue;
}
public PropertyBean getPropertyBean() {
return propertyBean;
}
public void setPropertyBean(PropertyBean propertyBean) {
this.propertyBean = propertyBean;
}
改进版本的延迟加载-Dispatcher
public class PropertyBean {
private String name;
private int value;
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public class ConcreteClassLazeLoader implements LazyLoader {
@Override
public Object loadObject() throws Exception {
System.out.println("lazy loadObject");
PropertyBean bean = new PropertyBean();
bean.setName("lazy loader name");
bean.setValue(11);
return bean;
}
public static void main(String []args){
LoaderBean loaderBean = new LoaderBean();
System.out.println(loaderBean.getLoaderName());
System.out.println(loaderBean.getLoaderValue());
PropertyBean bean = loaderBean.getPropertyBean();
//触发代理类的回调方法loadObject
System.out.println(bean.getName());
System.out.println(bean.getValue());
System.out.println("------");
//再次访问量,就不会加载了
System.out.println(bean.getName());
}
}/*loaderNameA
123
lazy loadObject
lazy loader name
11
------
lazy loader name*/
改进版本的延迟加载-Dispatcher
它和LazyLoader的区别在于:LazyLoader只在第一次访问延迟加载属性时触发代理类回调方法,而Dispatcher在每次访问延迟加载属性时触发代理类回调方法
public class LoaderBean {
private String loaderName;
private int loaderValue;
private PropertyBean propertyBean;//需要延迟加载的对象
public LoaderBean(){
this.loaderName = "loaderNameA";
this.loaderValue = 123;
this.propertyBean = createPropertyBean();//用ConcreteClassLazeLoader类完成代理类生成
}
protected PropertyBean createPropertyBean(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PropertyBean.class);
return (PropertyBean) enhancer.create(PropertyBean.class, new ConcreteClassLazeDispatcher());
}
public String getLoaderName() {
return loaderName;
}
public void setLoaderName(String loaderName) {
this.loaderName = loaderName;
}
public int getLoaderValue() {
return loaderValue;
}
public void setLoaderValue(int loaderValue) {
this.loaderValue = loaderValue;
}
public PropertyBean getPropertyBean() {
return propertyBean;
}
public void setPropertyBean(PropertyBean propertyBean) {
this.propertyBean = propertyBean;
}
}
public class PropertyBean {
private String name;
private int value;
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public class ConcreteClassLazeDispatcher implements Dispatcher {
@Override
public Object loadObject() throws Exception {
System.out.println("Dispatcher loadObject");
PropertyBean bean = new PropertyBean();
bean.setName("Dispatcher name");
bean.setValue(11);
return bean;
}
public static void main(String []args){
LoaderBean loaderBean = new LoaderBean();
System.out.println(loaderBean.getLoaderName());
System.out.println(loaderBean.getLoaderValue());
PropertyBean bean = loaderBean.getPropertyBean();
//触发代理类的回调方法loadObject
System.out.println(bean.getName());
System.out.println(bean.getValue());
System.out.println("------");
//再次访问量,也同样会触发代理类的回调方法loadObject
System.out.println(bean.getName());
}
}/*loaderNameA
123
Dispatcher loadObject
Dispatcher name
Dispatcher loadObject
11
------
Dispatcher loadObject
Dispatcher name*/
接口生成器-InterfaceMaker
它会动态生成一个接口,此接口包含指定类定义的所有方法
public class ConcreteClassNoInterface {
public String methodA(String str){
System.out.println("methodA:"+ str);
return str;
}
public int methodB(int n){
System.out.println("methodB:"+ n);
return n+10;
}
public int methodC(int n){
System.out.println("methodC:"+ n);
return n+10;
}
}
public class ConcreteClassInterfaceMaker {
public static void main(String []args){
InterfaceMaker interfaceMaker = new InterfaceMaker();
interfaceMaker.add(ConcreteClassNoInterface.class);
Class interfaceObj = interfaceMaker.create();
System.out.println(interfaceObj.isInterface());
System.out.println(interfaceObj.getName());
Method []methods = interfaceObj.getMethods();
for(Method method: methods){
System.out.println(method.getName());
}
}
}/*:)output
true
methodA
methodB
methodC*/