一:静态代理
在使用静态代理时,需要定义接口或者父类。被代理对象(目标对象)和代理对象都需要实现同一接口或者继承父类。
使用步骤:
1:定义一个接口IStudentDao
2:被代理对象(目标对象)StudentDao实现接口
3:代理对象StudentDaoProxy也需要实现接口
4:代理对象调用被代理对象方法
具体实现:
IStudentDao
public interface IStudentDao { void study(); }
StudentDao
public class StudentDao implements IStudentDao{ @Override public void study() { System.out.println("小明正在学习中..."); } }
StudentDaoProxy
public class StudentDaoProxy implements IStudentDao { private IStudentDao stu;//被代理对象,通过接口依赖 public StudentDaoProxy(IStudentDao stu) { this.stu = stu; } @Override public void study() { System.out.println("被代理对象方法执行前..."); //这里可以写一些增强方法 stu.study(); System.out.println("被代理对象方法执行后..."); } }
Client
public class Main { public static void main(String[] args) throws IllegalAccessException, InstantiationException { // IStudentDao stu = new StudentDao();//代理对象 IStudentDao proxyStu = new StudentDaoProxy(StudentDao.class.newInstance());//代理对象 proxyStu.study(); } }
运行结果:
二:JDK动态代理
jdk动态代理是代理模式实现的一种方法。也是需要实现接口的。主要是通过反射来动态生成代理类。被代理对象需要实现接口,代理对象不需要实现接口;
生成代理对象的JDK API:
/**
*loader:类加载器
*interfaces:被代理类实现的接口
*h:重写invocationHandler中的invoke,
*return:返回一个代理对象
*/
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
IStudentDao:
public interface IStudentDao { void study(); }
StudentDao
public class StudentDao implements IStudentDao { @Override public void study() { System.out.println("小明正在学习......"); } }
ProxyFactory:
//实现InvocationHandler接口,重写invoke方法
public class ProxyFactory implements InvocationHandler{ private Object target;//被代理的对象; public ProxyFactory(Object target) { this.target = target; } //返回一个代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("jdk代理开始"); Object invoke = method.invoke(target, args); System.out.println("jdk代理结束"); return invoke; } }
测试:
public class Main { public static void main(String[] args) throws IllegalAccessException, InstantiationException { IStudentDao stu = new StudentDao(); IStudentDao instance = (IStudentDao)new ProxyFactory(stu).getProxyInstance(); instance.study(); } }
结果:
三:cglib实现动态代理
无论是静态代理或者是jdk动态代理都需要实现一个接口。有时候我们只有一个对象,没有实现任何接口的。这时候可以使用目标对象子类来实现动态代理。cglib代理
通过在内存中构建子类从而实现对目标对象方法的扩建。
先导入依赖:
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.8</version> </dependency>
StudentDao
public class StudentDao { public void study() { System.out.println("小明正在学习......"); } }
ProxyFactory
public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getProxyInstance() { //1.创建一个工具类 Enhancer enhancer = new Enhancer(); //2.设置父类 enhancer.setSuperclass(target.getClass()); //3.设置回调函数 enhancer.setCallback(this); //4.创建子类,即代理对象 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib代理开始"); Object res = method.invoke(target, objects); System.out.println("cglib代理结束"); return res; } }
Main
public class Main { public static void main(String[] args) throws IllegalAccessException, InstantiationException { ProxyFactory proxyFactory = new ProxyFactory(StudentDao.class.newInstance()); StudentDao instance = (StudentDao)proxyFactory.getProxyInstance(); instance.study(); } }
四:总结
1:静态代理和jdk动态代理都需要实现接口,而cglib不用实现接口。
2:代理模式可以在不修改被代理对象(目标对象)的前提下,对目标对象进行扩展。
3:静态代理每次修改接口都需要维护目标对象和被代理对象。
4:你所热爱的,就是你的生活。