代码实战
ITeacherDao
1. public interface ITeacherDao { 2. void teach(); 3. void sayhello(String name); 4. 5. }
TeacherDao
1. public class TeacherDao implements ITeacherDao { 2. @Override 3. public void teach() { 4. System.out.println("老师授课中 。。。。。"); 5. } 6. 7. @Override 8. public void sayhello(String name) { 9. System.out.println("hello " + name); 10. } 11. }
ProxyFactory
1. public class ProxyFactory { 2. //维护一个目标对象 3. private Object target; 4. // 构造器,对target进行初始化 5. public ProxyFactory(Object target){ 6. this.target=target; 7. } 8. //给目标对象,生成一个代理对象 9. public Object getProxyInstance(){ 10. return Proxy.newProxyInstance(target.getClass().getClassLoader(), 11. target.getClass().getInterfaces(), new InvocationHandler() { 12. @Override 13. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 14. System.out.println("jdk 动态代理开始准备"); 15. Object invoke = method.invoke(target, args); 16. System.out.println("动态代理完成"); 17. return invoke; 18. } 19. }); 20. } 21. }
client
1. public class client { 2. public static void main(String[] args) { 3. ITeacherDao target = new TeacherDao(); 4. 5. ITeacherDao proxyInstance = (ITeacherDao) new ProxyFactory(target).getProxyInstance(); 6. // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象 7. System.out.println("proxyInstance=" + proxyInstance.getClass()); 8. //通过代理对象,调用目标对象的方法 9. //proxyInstance.teach(); 10. proxyInstance.sayhello(" tom "); 11. } 12. 13. }
Cglib 代理
Cglib 代理模式的基本介绍
1) 静态代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理
2) Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将 Cglib 代理归属到动态代理。
3) Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截
4) 在 AOP 编程中如何选择代理模式:
1. 目标对象需要实现接口,用 JDK 代理
2. 目标对象不需要实现接口,用 Cglib 代理
5) Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类
Cglib 代理模式实现步骤
1)导依赖
1. <dependencies> 2. <dependency> 3. <groupId>cglib</groupId> 4. <artifactId>cglib</artifactId> 5. <version>3.3.0</version> 6. </dependency> 7. </dependencies>
2)在内存中动态构建子类,注意代理的类不能为 final,否则报错
java.lang.IllegalArgumentException:
3) 目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
Cglib 代理模式应用实例
TeacherDao
1. public class TeacherDao { 2. public String teach() { 3. System.out.println(" 老师授课中 , 我是 cglib 代理,不需要实现接口 "); 4. return "hello"; 5. } 6. }
ProxyFactory
1. public class ProxyFactory implements MethodInterceptor { 2. //维护一个目标对象 3. private Object target; 4. 5. //构造器,传入一个被代理的对象 6. public ProxyFactory(Object target) { 7. this.target = target; 8. } 9. 10. //返回一个代理对象: 是 target 对象的代理对象 11. public Object getProxyInstance() { 12. //1. 创建一个工具类 13. Enhancer enhancer = new Enhancer(); 14. //2. 设置父类 15. enhancer.setSuperclass(target.getClass()); 16. //3. 设置回调函数 17. enhancer.setCallback(this); 18. //4. 创建子类对象,即代理对象 19. return enhancer.create(); 20. } 21. 22. @Override 23. public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 24. // TODO Auto-generated method stub 25. System.out.println("Cglib 代理模式 ~~ 开始"); 26. Object returnVal = method.invoke(target, args); 27. System.out.println("Cglib 代理模式 ~~ 提交"); 28. return returnVal; 29. } 30. }
Client
1. public class Client { 2. public static void main(String[] args) { 3. // TODO Auto-generated method stub 4. //创建目标对象 5. TeacherDao target = new TeacherDao(); 6. //获取到代理对象,并且将目标对象传递给代理对象 7. TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance(); 8. //执行代理对象的方法,触发 intecept 方法,从而实现 对目标对象的调用 9. String res = proxyInstance.teach(); 10. System.out.println("res=" + res); 11. } 12. }
几种常见的代理模式介绍
1) 防火墙代理
内网通过代理穿透防火墙,实现对公网的访问。
2) 缓存代理
比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok,如果取不到资源,再到公网或者数据库取,然后缓存。3) 远程代理
远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。
4) 同步代理:主要使用在多线程编程中,完成多线程间同步工作