package com.powernode.proxy.client;
import com.powernode.proxy.Spring6Config;
import com.powernode.proxy.service.OrderService;
import com.powernode.proxy.service.TimerInvocationHandler;
import com.powernode.proxy.service.impl.OrderServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
//创建目标对象
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
OrderService orderService = context.getBean("orderServiceImpl", OrderServiceImpl.class);
//创建代理对象
//类加载器,代理类要实现的接口,调用处理器.var返回对象即代理对象
//newProxyInstance新建代理对象实例
//本质上,这newProxyInstance()方法执行,在内存中动态生成了代理类的字节码,new了一个对象出来
//第一个参数 Classloader loader类加载器(代理类的类加载器必须得和被代理对象的类加载器一样)
//内存当中生成的字节码也是class文件,要执行也必须加载到内存中,加载类就需要类加载器,JDK要求目标类和代理类的加载器必须一样
//第二个参数 Class<?> interface代理类要实现的接口
//代理类和目标类要实现同一个接口或同一些接口,要通知JDK我们实现了什么接口,在内存中生成代理类的时候,需要告知实现了那些接口
//第三个参数 InvocationHandler handler调用处理器,是一个接口
//因为具体要增强什么代码,卸载调用处理器接口中写增强代码
Object o = Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), new TimerInvocationHandler(orderService));
//调用代理对象的代理方法
//之所以我们可以向下转型,因为我们实现了相同的接口
OrderService OS = (OrderService)o;
//调用代理对象的代理方法,如果是增强的话,目标对象的目标方法需要执行
OS.generate();
OS.Modify();
OS.detail();
}
}
package com.powernode.proxy.client;
import com.powernode.proxy.Spring6Config;
import com.powernode.proxy.service.OrderService;
import com.powernode.proxy.service.TimerInvocationHandler;
import com.powernode.proxy.service.impl.OrderServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
//创建目标对象
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spring6Config.class);
OrderService orderService = context.getBean("orderServiceImpl", OrderServiceImpl.class);
//创建代理对象
//类加载器,代理类要实现的接口,调用处理器.var返回对象即代理对象
//newProxyInstance新建代理对象实例
//本质上,这newProxyInstance()方法执行,在内存中动态生成了代理类的字节码,new了一个对象出来
//第一个参数 Classloader loader类加载器(代理类的类加载器必须得和被代理对象的类加载器一样)
//内存当中生成的字节码也是class文件,要执行也必须加载到内存中,加载类就需要类加载器,JDK要求目标类和代理类的加载器必须一样
//第二个参数 Class<?> interface代理类要实现的接口
//代理类和目标类要实现同一个接口或同一些接口,要通知JDK我们实现了什么接口,在内存中生成代理类的时候,需要告知实现了那些接口
//第三个参数 InvocationHandler handler调用处理器,是一个接口
//因为具体要增强什么代码,卸载调用处理器接口中写增强代码
Object o = Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), new TimerInvocationHandler(orderService));
//调用代理对象的代理方法
//之所以我们可以向下转型,因为我们实现了相同的接口
OrderService OS = (OrderService)o;
//调用代理对象的代理方法,如果是增强的话,目标对象的目标方法需要执行
OS.generate();
OS.Modify();
OS.detail();
}
}
package com.powernode.proxy.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimerInvocationHandler implements InvocationHandler
{
private static final Logger logger = LoggerFactory.getLogger(TimerInvocationHandler.class);
//目标对象
private Object obj;
//专门负责计时的调用处理器对象
//在这个调用处理器中编写负责计时的增强代码
//为什么要求必须实现InvocationHandler接口的方法,因为已经在其他引用中被调用了
//因为JDK底层已经调用了invoke方法
public TimerInvocationHandler(Object obj)
{
//赋值给成员变量
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//当代理对象调用代理方法的时候启用invoke方法,注册在invocationHandler接口中的invoke方法被调用
//该invoke方法存在的目的就是为了让我们可以写功能增强代码
//invoke方法是JDK负责调用的,所以我们可以直接使用里面的形参
//第一个参数是代理对象的引用,第二个是目标方法的目标方法(要执行的目标方法),第三个参数是目标方法上的实参
long begin = System.currentTimeMillis();
//调用目标对象的目标方法,方法四要素,谁调用,传什么值,回传什么参数,哪个方法
Object value = method.invoke(obj, args);
//invoke方法要调用目标对象的目标方法
long end = System.currentTimeMillis();
long time = end - begin;
logger.info("耗时" + time);
return value;
}
}
package com.powernode.proxy.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimerInvocationHandler implements InvocationHandler
{
private static final Logger logger = LoggerFactory.getLogger(TimerInvocationHandler.class);
//目标对象
private Object obj;
//专门负责计时的调用处理器对象
//在这个调用处理器中编写负责计时的增强代码
//为什么要求必须实现InvocationHandler接口的方法,因为已经在其他引用中被调用了
//因为JDK底层已经调用了invoke方法
public TimerInvocationHandler(Object obj)
{
//赋值给成员变量
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
//当代理对象调用代理方法的时候启用invoke方法,注册在invocationHandler接口中的invoke方法被调用
//该invoke方法存在的目的就是为了让我们可以写功能增强代码
//invoke方法是JDK负责调用的,所以我们可以直接使用里面的形参
//第一个参数是代理对象的引用,第二个是目标方法的目标方法(要执行的目标方法),第三个参数是目标方法上的实参
long begin = System.currentTimeMillis();
//调用目标对象的目标方法,方法四要素,谁调用,传什么值,回传什么参数,哪个方法
Object value = method.invoke(obj, args);
//invoke方法要调用目标对象的目标方法
long end = System.currentTimeMillis();
long time = end - begin;
logger.info("耗时" + time);
return value;
}
}
package com.powernode.proxy.service.impl;
import com.powernode.proxy.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
//缺点一:违背了OCP开闭原则,在运行良好的代码上进行了硬编码修改
//缺点二:代码没有得到复用,相同的代码写了很多遍
@Service
public class OrderServiceImpl implements OrderService
{
private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
@Override
public void generate()//目标方法
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(1234);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单已生成");
}
@Override
public void Modify()
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(456);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单已修改");
}
@Override
public void detail()
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(111);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单详情如下");
}
}
package com.powernode.proxy.service.impl;
import com.powernode.proxy.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
//缺点一:违背了OCP开闭原则,在运行良好的代码上进行了硬编码修改
//缺点二:代码没有得到复用,相同的代码写了很多遍
@Service
public class OrderServiceImpl implements OrderService
{
private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
@Override
public void generate()//目标方法
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(1234);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单已生成");
}
@Override
public void Modify()
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(456);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单已修改");
}
@Override
public void detail()
{
//模拟网络延迟,模拟生成延迟
try {
Thread.sleep(111);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("订单详情如下");
}
}
package com.powernode.proxy.service;
import org.springframework.stereotype.Service;
@Service
public interface OrderService//订单业务接口,也是代理对象和目标对象的公共接口
{
//生成订单
void generate();
//修改订单信息
void Modify();
//查看订单明细
void detail();
}
package com.powernode.proxy.service;
import org.springframework.stereotype.Service;
@Service
public interface OrderService//订单业务接口,也是代理对象和目标对象的公共接口
{
//生成订单
void generate();
//修改订单信息
void Modify();
//查看订单明细
void detail();
}
动态生成代理类,目的是减少代理类的数量,解决代码复用的问题
在内存中动态生成类的技术包括:JDK动态代理技术(java自带内置的,只能代理接口),
CGLIB(Code Generate Library)动态代理技术(开源框架,底层用继承方式代理(底层ASM字节码处理框架),可以代理类和接口),
Javassist动态代理技术
动态生成代理类,目的是减少代理类的数量,解决代码复用的问题
在内存中动态生成类的技术包括:JDK动态代理技术(java自带内置的,只能代理接口),
CGLIB(Code Generate Library)动态代理技术(开源框架,底层用继承方式代理(底层ASM字节码处理框架),可以代理类和接口),
Javassist动态代理技术