JDK动态代理被代理的类必须要实现有接口,而CGLIB动态代理被代理的类可实现接口也可不实现接口。
1.声明一个接口
package com.fh.service.aop;
public interface AopManager {
int add();
void list();
String delete();
void update();
void transfer();
}
2.实现一个接口的被代理类
package com.fh.service.aop.impl;
import org.springframework.stereotype.Service;
import com.fh.service.aop.AopManager;
@Service(“aopService”)
public class AopService implements AopManager{
@Override
public int add() {
// TODO Auto-generated method stub
System.out.println("AOPadd..........");
return 100;
}
@Override
public void list() {
// TODO Auto-generated method stub
System.out.println("AOPlist..........");
}
@Override
public String delete() {
// TODO Auto-generated method stub
System.out.println("AOPdelete.....");
return "delete ex";
}
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("update.........");
int i=1/0;
}
@Override
public void transfer() {
// TODO Auto-generated method stub
System.out.println("实现接口的动态代理增强类");
}
}
3.未实现接口的被代理类
package com.fh.service.aop.impl;
public class proxyService{
public void proxy() {
// TODO Auto-generated method stub
System.out.println("没有实现接口动态代理增强类");
}
}
4.使用JDK动态代理一个实现接口的被代理类
package com.fh.util.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.fh.service.aop.AopManager;
import com.fh.service.aop.impl.AopService;
/**JDK动态代理增强类
- @author Administrator
*/
public class JDKAdvice implements InvocationHandler {
//目标对象
private AopManager target;
public JDKAdvice() {
}
public JDKAdvice(AopManager target) {
this.target = target;
}
/**
* 代理方法, 每次调用目标对象方法时都会进到这里
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
return method.invoke(target, args);
}
/**
* 前置增强方法
*/
private void before() {
System.out.println("JDK动态代理前置增强通知");
}
public static void main(String[] args) {
//创建目标对象
AopManager target = new AopService();
//创建代理对象
AopManager proxy = (AopManager) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JDKAdvice(target)
);
//调用目标对象方法
proxy.transfer();
}
}
输出以下内容:
JDK动态代理前置增强通知
实现接口的动态代理增强类
5.使用JDK动态代理一个没有实现接口的被代理类(执行发生异常)
package com.fh.util.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.fh.service.aop.impl.proxyService;
public class ErrorJDKProxy implements InvocationHandler{
//目标对象
private proxyService target;
public ErrorJDKProxy(proxyService target) {
this.target = target;
}
/**
* 代理方法, 每次调用目标方法时都会进到这里
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
return method.invoke(target, args);
}
/**
* 前置增强
*/
private void before() {
System.out.println("JDK动态代理前置增强通知");
}
public static void main(String[] args) {
//创建目标对象
proxyService target = new proxyService();
//创建代理对象
proxyService proxy = (proxyService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new ErrorJDKProxy(target)
);
proxy.proxy();
}
}
输出以下内容:
Exception in thread “main” java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.fh.service.aop.impl.proxyService
at com.fh.util.aop.ErrorJDKProxy.main(ErrorJDKProxy.java:39)
6.使用CGLIB动态代理一个没有实现接口的被代理类
package com.fh.util.aop;
import java.lang.reflect.Method;
import com.fh.service.aop.impl.proxyService;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLIBAdvice implements MethodInterceptor {
/**
* 代理方法, 每次调用目标方法时都会进到这里
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
return methodProxy.invokeSuper(obj, args);
// return method.invoke(obj, args); 这种也行
}
/**
* 前置增强
*/
private void before() {
System.out.println("CGLIB动态代理前置增强通知");
}
public static void main(String[] args) {
//创建目标对象
proxyService target = new proxyService();
//创建代理对象
proxyService proxy = (proxyService) Enhancer.create(target.getClass(),
new CGLIBAdvice());
proxy.proxy();
}
}
输出以下内容:
CGLIB动态代理前置增强通知
没有实现接口动态代理增强类
JDK 和 CGLib动态代理性能对比
(1)CGLib所创建的动态代理对象在实际运行时候的性能要比JDK动态代理高不少,有研究表明,大概要高10倍。
(2)但是CGLib在创建对象的时候所花费的时间却比JDK动态代理要多很多,有研究表明,大概有8倍的差距。
(3)因此,对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,所以比较适合采用CGLib动态代理,反正,则比较适用JDK动态代理。