02_动态代理的实现

张创琦

代码部分见 Spring02

二者区别:

JDK需要提供interface 接口 ,而cglib不需要接口即可完成相关功能。

基础代码

AOP.java

  1. package com.kkb.aop;
  2. /**
  3. * 切面,服务代码,切入到核心代码当中,给了四个位置,
  4. */
  5. public interface AOP {
  6. void before();
  7. void exception();
  8. void after();
  9. void myFinally();
  10. }

LogAOP.java

  1. package com.kkb.aop;
  2. public class LogAOP implements AOP{
  3. @Override
  4. public void before() {
  5. System.out.println("日志------before------");
  6. }
  7. @Override
  8. public void exception() {
  9. System.out.println("日志------exception------");
  10. }
  11. @Override
  12. public void after() {
  13. System.out.println("日志------after------");
  14. }
  15. @Override
  16. public void myFinally() {
  17. System.out.println("日志------finally------");
  18. }
  19. }

TranAOP.java

  1. package com.kkb.aop;
  2. public class TranAOP implements AOP {
  3. @Override
  4. public void before() {
  5. System.out.println("事务-----before-----");
  6. }
  7. @Override
  8. public void exception() {
  9. System.out.println("事务-----exception-----");
  10. }
  11. @Override
  12. public void after() {
  13. System.out.println("事务-----after-----");
  14. }
  15. @Override
  16. public void myFinally() {
  17. System.out.println("事务-----finally-----");
  18. }
  19. }

IService.java

  1. package com.kkb.service;
  2. /**
  3. * 接口定义核心方法
  4. *
  5. */
  6. public interface IService {
  7. void add();
  8. }

TeamService.java

  1. package com.kkb.service;
  2. public class TeamService implements IService{
  3. @Override
  4. public void add(){
  5. System.out.println("TeamService--------add-------");
  6. }
  7. }

NBAService.java

  1. package com.kkb.cglibProxy;
  2. public class NBAService {
  3. public int add(String name, int id) {
  4. System.out.println("NBAService----add---");
  5. return id;
  6. }
  7. }

方法1: 基于JDK的动态代理

思想:逐步封装代码,提高代码的简洁性

1.1 基础代码

主要函数就是 teamService

测试:

  1. public static void main(String[] args) {
  2. //目标对象--被代理对象
  3. TeamService teamService = new TeamService();
  4. //返回代理对象 基于JDK的动态代理
  5. IService proxyService = (IService) Proxy.newProxyInstance(
  6. teamService.getClass().getClassLoader(),
  7. teamService.getClass().getInterfaces(),
  8. new InvocationHandler() { //回调函数,编写代理规则
  9. @Override
  10. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  11. try{
  12. System.out.println("开始事务");
  13. Object invoke = method.invoke(teamService, args);
  14. System.out.println("提交事务");
  15. return invoke;
  16. } catch(Exception e) {
  17. System.out.println("回滚事务");
  18. e.printStackTrace();
  19. throw e;
  20. } finally{
  21. System.out.println("finally---------");
  22. }
  23. }
  24. }
  25. );
  26. //代理对象干活
  27. proxyService.add();
  28. System.out.println(teamService.getClass()); //静态代理,地址为我们自己构建的TeamService
  29. System.out.println(proxyService.getClass()); //动态代理
  30. }

1.2 将 InvocationHandler 封装

ProxyHandler.java

  1. public class ProxyHandler implements InvocationHandler {
  2. private IService service;
  3. private AOP aop;
  4. public ProxyHandler(IService service, AOP aop) {
  5. this.service = service;
  6. this.aop = aop;
  7. }
  8. @Override
  9. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  10. try{
  11. aop.before();
  12. Object invoke = method.invoke(service, args);
  13. aop.after();
  14. return invoke;
  15. } catch(Exception e) {
  16. aop.exception();
  17. e.printStackTrace();
  18. throw e;
  19. } finally{
  20. aop.myFinally();
  21. }
  22. }
  23. }

测试:

  1. public static void main(String[] args) {
  2. //目标对象--被代理对象
  3. TeamService teamService = new TeamService();
  4. //切面
  5. AOP tranAOP = new TranAOP();
  6. //返回代理对象 基于JDK的动态代理
  7. IService proxyService = (IService) Proxy.newProxyInstance(
  8. teamService.getClass().getClassLoader(),
  9. teamService.getClass().getInterfaces(),
  10. new ProxyHandler(teamService, tranAOP)
  11. );
  12. //代理对象干活
  13. proxyService.add();
  14. System.out.println(teamService.getClass());
  15. System.out.println(proxyService.getClass());
  16. }

1.3 JDK动态类全部封装

ProxyFactory.java

  1. package com.kkb.dynamicProxy;
  2. import com.kkb.aop.AOP;
  3. import com.kkb.service.IService;
  4. import java.lang.reflect.InvocationHandler;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.Proxy;
  7. public class ProxyFactory {
  8. private IService service; //目标对象
  9. private AOP aop; //切面
  10. public ProxyFactory(IService service, AOP aop) {
  11. this.service = service;
  12. this.aop = aop;
  13. }
  14. /**
  15. * 获取动态代理的实例
  16. * @return
  17. */
  18. public Object getProxyInstance() {
  19. return Proxy.newProxyInstance(
  20. service.getClass().getClassLoader(),
  21. service.getClass().getInterfaces(),
  22. new InvocationHandler() { //回调函数,编写代理规则
  23. @Override
  24. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  25. try{
  26. aop.before();
  27. Object invoke = method.invoke(service, args);
  28. aop.after();
  29. return invoke;
  30. } catch(Exception e) {
  31. aop.exception();
  32. e.printStackTrace();
  33. throw e;
  34. } finally{
  35. aop.myFinally();
  36. }
  37. }
  38. }
  39. );
  40. }
  41. }

测试:

  1. public static void main(String[] args) {
  2. IService teamService = new TeamService();
  3. AOP tranAOP = new TranAOP();
  4. AOP logAOP = new LogAOP();
  5. IService service = (IService) new ProxyFactory(teamService, tranAOP).getProxyInstance();
  6. IService service1 = (IService) new ProxyFactory(service, logAOP).getProxyInstance();
  7. service1.add(); //核心业务+服务代码 混合在一起的完整代码
  8. }

方法2: 基于cglib的动态代理

2.1 基础代码

  1. public static void main1(String[] args) {
  2. //目标对象:没有接口
  3. NBAService nbaService = new NBAService();
  4. //cglib代理
  5. NBAService proxyService = (NBAService) Enhancer.create(nbaService.getClass(),
  6. new MethodInterceptor(){ // 回调函数负责编写代理规则
  7. @Override
  8. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  9. try{
  10. System.out.println("事务开始");
  11. Object invoke = methodProxy.invokeSuper(o, objects); //最关注的核心的部分
  12. System.out.println("事务提交");
  13. return invoke;
  14. } catch(Exception e) {
  15. System.out.println("事务回滚");
  16. throw e;
  17. } finally{
  18. System.out.println("finally----------");
  19. }
  20. }
  21. });
  22. //代理对象干活
  23. int res = proxyService.add("huren", 1001);
  24. System.out.println(res);
  25. }

2.2 将回调函数封装

CglibProxyFactory.java

此处事务没有实现接口,而是直接声明了它的Service .

  1. package com.kkb.cglibProxy;
  2. import com.kkb.aop.AOP;
  3. import net.sf.cglib.proxy.Enhancer;
  4. import net.sf.cglib.proxy.MethodInterceptor;
  5. import net.sf.cglib.proxy.MethodProxy;
  6. import java.lang.reflect.Method;
  7. public class CglibProxyFactory {
  8. //目标对象,没有实现接口
  9. private NBAService nbaService;
  10. //切面
  11. private AOP aop;
  12. public Object getProxyInstance(NBAService nbaService, AOP aop){
  13. return Enhancer.create(nbaService.getClass(), new MethodInterceptor() {
  14. @Override
  15. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  16. try{
  17. aop.before();
  18. Object o1 = methodProxy.invokeSuper(o, objects);
  19. aop.after();
  20. return o1;
  21. } catch(Exception e) {
  22. aop.exception();
  23. throw e;
  24. } finally{
  25. aop.myFinally();
  26. }
  27. }
  28. });
  29. }
  30. }

测试:

  1. public static void main2(String[] args) {
  2. NBAService nbaService = new NBAService();
  3. AOP tranAop = new TranAOP();
  4. NBAService proxyInstance = (NBAService) new CglibProxyFactory().getProxyInstance(nbaService, tranAop);
  5. int res = proxyInstance.add("huren", 1001);
  6. System.out.println(res);
  7. }