JDK动态代理
主要涉及java.lang.reflect包下的两个类:Proxy和InvocationHandler。InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。而Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
public interface UserService {
public String getName(int id);
}
public class UserServiceImpl implements UserService{
@Override
public String getName(int id) {
return "user "+id;
}
}
采用jdk动态代理
public class MyInvocationHandler implements InvocationHandler{
private Object target;
public MyInvocationHandler(){
super();
}
public MyInvocationHandler(Object target){
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---before----"+method.getName());
Object result = method.invoke(target, args);
System.out.println(result);
System.out.println("---after-----"+method.getName());
return result;
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invocationHandler = new MyInvocationHandler(userService);
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), invocationHandler);
System.out.println(userServiceProxy.getName(1));
}
CGLIB动态代理
采用底层的字节码技术,可以为一个类创建子类。在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。由于CGLib采用动态创建子类的方式生成代理对象,所以不能对目标类的final或private方法进行代理。
public class CglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("----before---"+methodProxy.getSuperName());
Object result = methodProxy.invokeSuper(target, args);
System.out.println(result);
System.out.println("---after------"+methodProxy.getSuperName());
return result;
}
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(cglibProxy);
UserService userService = (UserService) enhancer.create();
userService.getName(2);
}
}
实验表明,DGLIB动态代理创建的对象的性能比JDK所创建的动态代理对象的性能高(大概10倍),但它在创建代理对象时所花费的时间却比JDK动态代理多。(大概8倍).