***机制原理及实操
***的作用:代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法
静态***:
***类由程序员创建的然后编译成.class文件。但是其中缺点是,具有重复代码,灵活性不好,例如在执行接口A中所有方法之前加上日志逻辑,那么使用静态***的话,在***类中每个方法都得加上
动态***:
是在运行的时候,通过jvm中的反射进行动态创建对象,生成字节码对象(构造方法参数 InvocationHandler h类型),传入由我们实现InvocationHandler接口的对象,通过反射创建***对象。 然后当调用***对象的任何方法都会调用h中的 invoke(Object proxy,Method method,Object[] args)传入当前***对象、当前调用的方法、方法参数值。
动态***的优势是实现无侵入式的代码扩展,也就是方法的增强;让你可以在不用修改源码的情况下,增强一些方法;在方法的前后你可以做你任何想做的事情(甚至不去执行这个方法就可以)。
动态***分两种:
jdk方式的***是对类的接口以及接口的对象进行***
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class DirectJDKProxy {
// 对接口以及接口对象进行***
public static Object getProxy(Object object) {
Class<?> klass=object.getClass();
// 获取类加载器
ClassLoader classLoader=klass.getClassLoader();
// 获取类的接口
Class<?> [] interfaces=klass.getInterfaces();
// 返回***对象
return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进行前置拦截");
Object result=method.invoke(object, args);
System.out.println("进行后置拦截");
System.out.println("进行了jdk***");
return result;
}
});
}
}
核心:
Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
}
• proxy => 这个参数指定动态生成的***类,这里是
• method => 这个参数表示传入接口中的所有Method对象
• args => 这个参数对应当前method方法中的参数
Cglib方式的*** 需要jar包
package proxy;
import java.lang.reflect.Method;
import org.omg.CORBA.PUBLIC_MEMBER;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy {
private static Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public CglibProxy() {
}
private static Object innerProxy(Object object) {
Class<?> parentclass=object.getClass();
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(parentclass);
// 回调函数 指向函数的指针
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable {
System.out.println(proxy.getClass());
System.out.println(proxy instanceof SomeClass);
System.out.println("进行前置拦截");
Object result=method.invoke(object, arg2);
System.out.println("进行后置拦截");
System.out.println();
return result;
}
});
return enhancer.create();
}
public static Object getProxy() {
if (object==null) {
return null;
}
return innerProxy(object);
}
public static Object getProxy(Class<?> klass) {
Object object;
if(klass!=null) {
try {
object=klass.newInstance();
return innerProxy(object);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return null;
}
}
核心:
enhancer.setSuperclass(parentclass);
// 回调函数 指向函数的指针
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy methodProxy)
给出测试类
package proxy;
public class SomeClass implements ISomeClass{
public SomeClass() {
}
@Override
public String DealString(String str) {
str="["+str+"]";
System.out.println(str);
return str;
}
package proxy;
Test 测试:
public class Test {
public Test() {
}
public static void main(String[] args) {
SomeClass someClass=new SomeClass();
ISomeClass someclassProxy=(ISomeClass) DirectJDKProxy.getProxy(someClass);
someclassProxy.DealString("快来***我呀");
CglibProxy cProxy=new CglibProxy();
SomeClass sClass=(SomeClass) cProxy.getProxy(SomeClass.class);
sClass.DealString("快来***我呀");
动态***的应用:RPC框架,Spring AOP机制,进行日志的书写