JDK动态代理
被代理对象需要有接口
准备目标类
public interface DeptService {
//列表查询
List<Dept> findAll();
//保存
void save(Dept dept);
//根据id查询
Dept findById(Integer id);
}
public class DeptServiceImpl implements DeptService {
@Override
public List<Dept> findAll() {
System.out.println("findAll 查询列表");
return new ArrayList<>();
}
@Override
public void save(Dept dept) {
System.out.println("save 保存成功");
}
@Override
public Dept findById(Integer id) {
//System.out.println(1 / 0);
System.out.println("findById 根据id查询");
return new Dept();
}
}
准备增强类
public class Logger {
public void m1() {
System.out.println("方法执行之前" + LocalDateTime.now());
}
public void m2() {
System.out.println("方法运行结束" + LocalDateTime.now());
}
public void m3() {
System.out.println("方法出现异常" + LocalDateTime.now());
}
}
创建代理工厂
// JDK动态代理(基于接口)【工厂】
// 基于JDK动态代理产生的代理对象与被代理对象是兄弟关系,二者实现同一个接口
public class JDKProxyFactory {
public static Object getProxy(Class clazz) {
// 生成代理对象
Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Logger logger = new Logger();
Object obj = null;
try {
// 前置增强
logger.m1();
// method.invoke() :被代理的对象执行方法
obj = method.invoke(clazz.newInstance(), args);
// 后置增强
logger.m2();
} catch (Exception e) {
e.printStackTrace();
logger.m3();
}
return obj;
}
});
return proxy;
}
}
修改测试代码
// 测试类
public class DeptServiceTest {
@Test
public void test1() {
DeptService deptService = new DeptServiceImpl();
deptService.findAll();
}
@Test
public void jdkProxyTest() {
// JDK动态代理:基于DeptService接口,动态的实现一个实现类对象,进行增强
DeptService deptService = (DeptService) JDKProxyFactory.getProxy(DeptServiceImpl.class);
deptService.findById(2);
}
}
Cglib动态代理
被代理对象可以被继承
准备目标类,删除接口
public class DeptServiceImpl {
public List<Dept> findAll() {
System.out.println("findAll 查询列表");
return new ArrayList<>();
}
public void save(Dept dept) {
System.out.println("save 保存成功");
}
public Dept findById(Integer id) {
System.out.println("findById 根据id查询");
return new Dept();
}
}
创建代理工厂
// Cglib动态代理(基于继承)【工厂】
// 基于Cglib动态代理产生的代理对象与被代理对象是父子关系,代理对象是被代理对象的儿子
// 前提条件:被代理对象可以被继承,除非这个类被final修饰了,成了最终类,那么这个类就不能被继承了
public class CglibProxyFactory {
public static Object getProxy(Class clazz) {
// 创建一个代理工具类
Enhancer enhancer = new Enhancer();
// 根据父类创建子类对象
enhancer.setSuperclass(clazz);
// 调用代理对象的方法(增强的代码写在这里)
enhancer.setCallback(new InvocationHandler() {
//参数一:代理对象本身(用不上它)
//参数二:代理对象方法
//参数三:方法的参数
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Logger logger = new Logger();
// 前置增强
logger.m1();
// 执行被代理对象的方法
Object invoke = method.invoke(clazz.newInstance(), objects);
// 后置增强
logger.m2();
// 返回方法执行的返回值
return invoke;
}
});
// 生成代理对象并返回
Object proxy = enhancer.create();
return proxy;
}
}
修改测试代码
// 测试类
public class DeptServiceTest {
@Test
public void test1() {
DeptServiceImpl deptService = new DeptServiceImpl();
deptService.findAll();
}
@Test
public void cglibProxyTest() {
DeptServiceImpl deptService = (DeptServiceImpl) CglibProxyFactory.getProxy(DeptServiceImpl.class);
deptService.findById(1);
}
}
小结
1、动态代理好处:把核心业务和非核心业务解耦,避免业务代码冗余。
2、核心类和方法:Proxy.newProxyInstance。
3、核心参数:new InvocationHandler() 的 invoke方法。
4、首先明确在创建代理实现类时,jdk的速度要高于cglib,所以选择的时候:
(1)当被代理类有接口的时候,使用jdk动态代理;
(2)当被代理类没有接口的时候,使用cglib动态代理。