当我们需要在一个方法的前后打印日志的时候,我们通常想到的办法就是在调用这个方法的前后进行打印,今天我们就来看一下java里面的反射机制如何在方法前后进行打印.
首先,我们介绍一下代理(Proxy):对被代理对象(xxx)所有的方法进行"拦截和控制".
下面,我们通过一段简短的代码认识一下动态代理:
关于类加载器的作用:
1.将硬盘上的class文件加载到内存的方法区中进行存储;
2.当class文件加载完成之后,类加载器会在堆区中创建一个用于描述该方法区中代码结构的一个Class对象
下面来看整个动态代理的实现:
public interface SuperStar {
void sing( int money );
void liveShow( int money );
void sleep();
}
public class XXX implements SuperStar {
@Override
public void sing( int money ) {
System.out.println( "某明星准备唱歌去!" );
System.out.println( "赚了: " + money + "块钱" );
}
@Override
public void liveShow( int money ) {
System.out.println( "演唱<<Running Man>>!" );
System.out.println( "获得了 : " + money + "块钱" );
}
@Override
public void sleep() {
System.out.println( "某明星和某富豪...Zzzz~~" );
}
}
public class SuperStarDemo {
@Test
public void demo01() {
// 1. 创建一个实例对象
XXX xxx = new XXX();
// 2.对象的方法
xxx.sing( 5 );
xxx.liveShow( 10 );
xxx.sleep();
}
@Test
public void demo02() {
// 1. 创建一个实例对象
final XXX xxx = new XXX();
// 到底执行什么方法,取决于真实类
// 代理proxy :对被代理对象所有的方法进行"拦截和控制".
// 引导类/根类加载器,扩展类加载器,应用类加载器
/************** 创建动态代理的代码start ******************/
ClassLoader loader = SuperStarDemo.class.getClassLoader();
// ClassLoader loader = xxx.getClass()
// .getClassLoader();
System.out.println( loader );
Class<?>[] interfaces = xxx.getClass()
.getInterfaces();
// new InvocationHandler(){} 匿名接口实现类对象
SuperStar proxy = (SuperStar) Proxy.newProxyInstance( loader, interfaces, new InvocationHandler() {
@Override
public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {
// 打印方法名称和参数
// System.out.println(method.getName());
// System.out.println(Arrays.toString(args));
// 打印代理类
System.out.println( proxy.getClass() ); // proxy.toString();
// Object proxy代理类本身
// Method 调用当前执行的方法
// Object[] args 当前执行方法的实际参数
// return method.invoke(目标类实例, args);
// 1. 获取当前方法
String methodName = method.getName();
// 2. 方法判断
if ( "sing".equals( methodName ) ) {
// 获取参数
int money = (int) args[ 0 ];
// 判断
if ( money < 10000 ) {
System.out.println( "钱太少了不干..." );
return null; // 跳出
}
// 打印
System.out.println( "代理分成: " + money * 0.3 );
// 执行方法
return method.invoke( xxx, (int) ( money * 0.7 ) );
} else if ( "liveShow".equals( methodName ) ) {
// 获取参数
int money = (int) args[ 0 ];
// 判断
if ( money < 100000 ) {
System.out.println( "hi, How old are you. money too shao le..." );
return null; // 跳出
}
// 打印
System.out.println( "代理分成: " + money * 0.3 );
// 执行方法并跳出
return method.invoke( xxx, (int) ( money * 0.7 ) );
} else {
return method.invoke( xxx, args );
}
}
} );
/************** 创建动态代理的代码end ******************/
// 2. 应该调用代理类对象的方法
proxy.sing( 10000 );
proxy.liveShow( 100000 );
proxy.sleep();
}
}
以上,是动态代理的简单实现.