jdk 动态代理
- JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能用这种办法生成代理对象。
public interface Sell {
void sell();
void ad();
}
public class Vendor implements Sell{
@Override
public void sell() {
System.out.println("Shop sell goods");
}
@Override
public void ad() {
System.out.println("Shop advert goods");
}
}
package com.company;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;
public class LogHandler implements InvocationHandler {
Object target; // 被代理的对象,实际的方法执行者
public LogHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args); // 调用 target 的 method 方法
after();
return result; // 返回方法的执行结果
}
// 调用invoke方法之前执行
private void before() {
System.out.println("log start");
}
// 调用invoke方法之后执行
private void after() {
System.out.println("log end ");
}
}
package com.company;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
// write your code here
// 创建中介类实例
LogHandler logHandler = new LogHandler(new Vendor());
// 设置该变量可以保存动态代理类,默认名称$Proxy0.class
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// 获取代理类实例Sell
Sell sell = (Sell) (Proxy.newProxyInstance(Sell.class.getClassLoader(), new Class[]{Sell.class}, logHandler));
// 通过代理类对象调用代理类方法,实际上会转到invoke方法调用
sell.sell();
sell.ad();
}
}
output
log start
Shop sell goods
log end
log start
Shop advert goods
log end
cglib
- Cglib动态代理采用的是创建目标类的子类的方式。优点:不用实现额外接口,只操作我们关心类,高性能。基于ASM机制实现,通过生成业务类的子类作为代理类。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class UserDao {
public void findAllUsers(){
System.out.println("UserDao findAllUsers");
}
public String findUsernameById(int id){
System.out.println("UserDao findUsernameById");
return "findUsernameById";
}
}
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class LogInterceptor implements MethodInterceptor {
/**
*
* @param obj 表示要进行增强的对象
* @param method 表示拦截的方法
* @param objects 数组表示参数列表,基本数据类型需要传入其包装类型,如int-->Integer、long-Long、double-->Double
* @param methodProxy 表示对方法的代理,invokeSuper方法表示对被代理对象方法的调用
* @return 执行结果
* @throws Throwable 异常
*/
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before(method.getName());
// 注意这里是调用invokeSuper而不是invoke,否则死循环;
// methodProxy.invokeSuper执行的是原始类的方法;
// method.invoke执行的是子类的方法;
Object result = methodProxy.invokeSuper(obj, objects);
after(method.getName());
return result;
}
/**
* 调用invoke方法之前执行
*/
private void before(String methodName) {
System.out.println("调用方法" + methodName +"之【前】的日志处理");
}
/**
* 调用invoke方法之后执行
*/
private void after(String methodName) {
System.out.println("调用方法" + methodName +"之【后】的日志处理");
}
}
import net.sf.cglib.proxy.Enhancer;
public class Main {
public static void main(String[] args) {
// 通过CGLIB动态代理获取代理对象的过程
// 创建Enhancer对象,类似于JDK动态代理的Proxy类
Enhancer enhancer = new Enhancer();
// 设置目标类的字节码文件
enhancer.setSuperclass(UserDao.class);
// 设置回调函数
enhancer.setCallback(new LogInterceptor());
// create方法正式创建代理类
UserDao userDao = (UserDao) enhancer.create();
// 调用代理类的具体业务方法
userDao.findAllUsers();
userDao.findUsernameById(1);
}
}
output
调用方法findAllUsers之【前】的日志处理
UserDao findAllUsers
调用方法findAllUsers之【后】的日志处理
调用方法findUsernameById之【前】的日志处理
UserDao findUsernameById
调用方法findUsernameById之【后】的日志处理
Process finished with exit code 0
ref
网友评论