仅作为个人学习笔记
1. 代理模式
使用代理对象代替对真实对象的访问,达到在不修改源代码的前提下实现功能的扩展
2. 静态代理
静态代理在编译时将接口、实现类、代理变成实际的class文件
2.1 静态代理实现步骤
(1)定义一个接口及其实现类(目标类)
(2)定义一个代理类,实现该接口
(3)将目标对象注入代理类、然后在代理类的对应方法调用目标类中的对应方法。
在代理类的对应方法中屏蔽对目标类的直接访问,并实现在执行目标类对应方法前后功能的扩展
定义接口与其实现类
//生产衣服接口
public interface ClothFactory {
int produce();
}
public class ClothFactoryNike implements ClothFactory{
@Override
public int produce() {
System.out.println("生产Nike");
return 0;
}
}
定义代理类
public class NikeProxy implements ClothFactory{
private ClothFactory clothFactory;
public NikeProxy(ClothFactoryNike clothFactoryNike) {
this.clothFactory = clothFactoryNike;
}
@Override
public int produce() {
System.out.println("前置功能增强");
int res = clothFactory.produce();
System.out.println("后置功能增强");
return res;
}
}
使用静态代理
public class NikeTest {
@Test
public void test(){
ClothFactory clothFactory = new ClothFactoryNike();
NikeProxy nikeProxy = new NikeProxy(clothFactory);
nikeProxy.produce();
}
}
3. 动态代理
动态代理不需要对每个目标类都单独创建一个代理类,也不需要我们必须实现接口,是在运行时动态生成类字节码,并加载到JVM中。
动态代理包括CGLIB和JDK动态代理
3.1JDK动态代理
核心:InvocationHandler 接口和 Proxy 类
其中,Proxy类中的核心方法是newProxyInstance(),用来生产代理对象
参数包括 类加载器loader、被代理类实现的接口interfaces和实现InvocationHandler接口的对象handler
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
...
}
JDK动态代理步骤:
1、创建被代理类的接口及其实现类
2、自定义InvocationHandler接口的实现类,重写其中的invoke方法
3、通过Proxy.newProxyInstance方法创建代理对象
//被代理接口
public interface ClothFactory {
int produce();
}
//被代理接口的实现类
public class ClothFactoryNike implements ClothFactory{
@Override
public int produce() {
System.out.println("生产Nike");
return 0;
}
}
//定义一个Handler接口实现类,重写invoke方法
public class NikeProxy1 implements InvocationHandler {
private Object obj;
public NikeProxy1(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"的前置增强");
Object res = method.invoke(obj,args);
System.out.println(method.getName()+"的后置增强");
return res;
}
}
//定义一个代理工厂,用来获取代理类的实例对象
public class NikeProxyFactory {
public static Object getProxyInstance(Object target){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new NikeProxy1(target));
}
}
//测试
@Test
public void test1(){
ClothFactoryNike clothFactoryNike = new ClothFactoryNike();
ClothFactory instance = (ClothFactory) NikeProxyFactory.getProxyInstance(clothFactoryNike);
instance.produce();
}
然而,JDL代理类只能代理接口或者实现接口的类,对于为实现接口的类无法代理。
3.2 CGLIB动态代理
代理对象在底层创建了一个子类进行逻辑增强。
核心: MethodInterceptor 接口和 Enhancer 类
其中,MethodInterceptor 接口中的interceptor用于拦截并增强被代理类,类似于JDK代理中的invoke方法
public interface MethodInterceptor
extends Callback{
// 拦截被代理类中的方法
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,MethodProxy proxy) throws Throwable;
}
CGLIB动态代理的使用步骤
1、定义一个类
2、创建一个实现MethodInterceptor接口的类
3、通过Enhancer类的create()方法创建代理类
//定义被代理类
public class AdidasFactory {
public void produce(){
System.out.println("生产Adidas服饰");
}
}
//定义MethodInterceptor接口实现类
public class AdidasProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName()+"的前置方法");
Object res = methodProxy.invokeSuper(o, objects);
System.out.println(method.getName()+"的后置方法");
return res;
}
}
//定义代理工厂,用于获取代理示例
public class AdidasProxyFactory {
public static Object getProxy(Class<?> clazz){
//动态代理增强类
Enhancer enhancer = new Enhancer();
//设置类加载器
enhancer.setClassLoader(clazz.getClassLoader());
//设置被代理类
enhancer.setSuperclass(clazz);
//设置方法拦截
enhancer.setCallback(new AdidasProxy());
//创建代理类对象
return enhancer.create();
}
}
//测试
@Test
public void cgProxy(){
AdidasFactory adidasFactory1 = (AdidasFactory) AdidasProxyFactory.getProxy(AdidasFactory.class);
adidasFactory1.produce();
}