JDK代理
基本使用
public class JDKProxy<T> implements InvocationHandler {
private T target;
public void setTarget(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdk proxy before");
Object ret = method.invoke(target, args);
System.out.println("jdk proxy after");
return ret;
}
public static void main(String[] args) {
JDKProxy<TargetService> jdkProxy = new JDKProxy<>();
jdkProxy.setTarget(new TargetService());
Service service = (Service) Proxy.newProxyInstance(TargetService.class.getClassLoader(), TargetService.class.getInterfaces(), jdkProxy);
service.print();
}
}
原理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import jiankunking.Subject;
public final class ProxySubject
extends Proxy
implements Subject
{
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public ProxySubject(InvocationHandler paramInvocationHandler)
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String SayGoodBye()
{
try
{
return (String)this.h.invoke(this, m3, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String SayHello(String paramString)
{
try
{
// 这里传的是接口的方法, 第一个参数是代理类的实例
return (String)this.h.invoke(this, m4, new Object[] { paramString });
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
//由于jdk是代理的接口,所以关注下m3,m4 是接口的方法,而不是实现类的方法。
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("jiankunking.Subject").getMethod("SayGoodBye", new Class[0]);
m4 = Class.forName("jiankunking.Subject").getMethod("SayHello", new Class[] { Class.forName("java.lang.String") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
public Object invoke(Object proxy, Method method, Object[] args)
proxy:是代理类的实例
method:是接口的方法,所以我们在使用spring中的aop时,获得方法时接口的方法;所以标注的在实现类中的注解时获得不到的。
args:参数
cglib代理
基本使用
public class CglibProxy<T> implements MethodInterceptor {
private T target;
public void setTarget(T target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib proxy before");
//只调用自己的方法
Object ret = method.invoke(target, objects);
// 通过父类方法调用自己
// methodProxy.invokeSuper(o, objects);
System.out.println("cglib proxy after");
return null;
}
public static void main(String[] args) {
TargetService service = new TargetService();
CglibProxy<TargetService> cglibProxy = new CglibProxy<>();
cglibProxy.setTarget(service);
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(service.getClass());
enhancer.setCallback(cglibProxy);
Service proxyService = (Service) enhancer.create();
proxyService.print();
}
}
原理
// 通过子类调用父类的方法
final void CGLIB$gotoHome$0() {
super.gotoHome();
}
// 创建一个子类,重写父类的方法。
public final void gotoHome() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
// CGLIB$gotoHome$0$Method是被代理类的方法。
var10000.intercept(this, CGLIB$gotoHome$0$Method, CGLIB$emptyArgs, CGLIB$gotoHome$0$Proxy);
} else {
super.gotoHome();
}
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
o:代理类
method:实现类的方法,所以这种是可以获取到方法中的注解的。
objects:参数
methodProxy:方法代理,可以通过该类,调用子类的方法,在子类中调用父类的方法:
// 直接调用被代理类的方法,所以在这个方法中如果调用自身的方法,是调用的被代理的方法
method.invoke(target, objects);
// 调用父类中的代理方法,该方法调用父类的方法,
// 如果在被代理类中调用自身方法,会调用子类的方法;
methodProxy.invokeSuper(o, objects);
举例子:
使用method.invoke(target, objects);
public class TargetService implements Service {
@Override
public void print() {
System.out.println("target method");
// 调用自身方法
test();
}
public void test() {
System.out.println("target test ...");
}
}
这里调用的被代理类的方法
cglib proxy before
target method
target test ...
cglib proxy after
使用methodProxy.invokeSuper(o, objects);
调用的是子类中的方法,所以在进入到test方法后会进入了代理方法。
cglib proxy before
target method
cglib proxy before
target test ...
cglib proxy after
cglib proxy after
所以在@Transactional的方法中,调用自身方法不能生效。而在@configuraton注解中生效,得到bean对象。(代理中判断如果有实例了就从IOC容器中取,否则就调用@Bean方法实例化。)