02_动态代理的实现
张创琦
代码部分见 Spring02
二者区别:
JDK需要提供interface 接口 ,而cglib不需要接口即可完成相关功能。
基础代码
AOP.java
package com.kkb.aop;/*** 切面,服务代码,切入到核心代码当中,给了四个位置,*/public interface AOP {void before();void exception();void after();void myFinally();}
LogAOP.java
package com.kkb.aop;public class LogAOP implements AOP{@Overridepublic void before() {System.out.println("日志------before------");}@Overridepublic void exception() {System.out.println("日志------exception------");}@Overridepublic void after() {System.out.println("日志------after------");}@Overridepublic void myFinally() {System.out.println("日志------finally------");}}
TranAOP.java
package com.kkb.aop;public class TranAOP implements AOP {@Overridepublic void before() {System.out.println("事务-----before-----");}@Overridepublic void exception() {System.out.println("事务-----exception-----");}@Overridepublic void after() {System.out.println("事务-----after-----");}@Overridepublic void myFinally() {System.out.println("事务-----finally-----");}}
IService.java
package com.kkb.service;/*** 接口定义核心方法**/public interface IService {void add();}
TeamService.java
package com.kkb.service;public class TeamService implements IService{@Overridepublic void add(){System.out.println("TeamService--------add-------");}}
NBAService.java
package com.kkb.cglibProxy;public class NBAService {public int add(String name, int id) {System.out.println("NBAService----add---");return id;}}
方法1: 基于JDK的动态代理
思想:逐步封装代码,提高代码的简洁性
1.1 基础代码
主要函数就是 teamService
测试:
public static void main(String[] args) {//目标对象--被代理对象TeamService teamService = new TeamService();//返回代理对象 基于JDK的动态代理IService proxyService = (IService) Proxy.newProxyInstance(teamService.getClass().getClassLoader(),teamService.getClass().getInterfaces(),new InvocationHandler() { //回调函数,编写代理规则@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try{System.out.println("开始事务");Object invoke = method.invoke(teamService, args);System.out.println("提交事务");return invoke;} catch(Exception e) {System.out.println("回滚事务");e.printStackTrace();throw e;} finally{System.out.println("finally---------");}}});//代理对象干活proxyService.add();System.out.println(teamService.getClass()); //静态代理,地址为我们自己构建的TeamServiceSystem.out.println(proxyService.getClass()); //动态代理}
1.2 将 InvocationHandler 封装
ProxyHandler.java
public class ProxyHandler implements InvocationHandler {private IService service;private AOP aop;public ProxyHandler(IService service, AOP aop) {this.service = service;this.aop = aop;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try{aop.before();Object invoke = method.invoke(service, args);aop.after();return invoke;} catch(Exception e) {aop.exception();e.printStackTrace();throw e;} finally{aop.myFinally();}}}
测试:
public static void main(String[] args) {//目标对象--被代理对象TeamService teamService = new TeamService();//切面AOP tranAOP = new TranAOP();//返回代理对象 基于JDK的动态代理IService proxyService = (IService) Proxy.newProxyInstance(teamService.getClass().getClassLoader(),teamService.getClass().getInterfaces(),new ProxyHandler(teamService, tranAOP));//代理对象干活proxyService.add();System.out.println(teamService.getClass());System.out.println(proxyService.getClass());}
1.3 JDK动态类全部封装
ProxyFactory.java
package com.kkb.dynamicProxy;import com.kkb.aop.AOP;import com.kkb.service.IService;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyFactory {private IService service; //目标对象private AOP aop; //切面public ProxyFactory(IService service, AOP aop) {this.service = service;this.aop = aop;}/*** 获取动态代理的实例* @return*/public Object getProxyInstance() {return Proxy.newProxyInstance(service.getClass().getClassLoader(),service.getClass().getInterfaces(),new InvocationHandler() { //回调函数,编写代理规则@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try{aop.before();Object invoke = method.invoke(service, args);aop.after();return invoke;} catch(Exception e) {aop.exception();e.printStackTrace();throw e;} finally{aop.myFinally();}}});}}
测试:
public static void main(String[] args) {IService teamService = new TeamService();AOP tranAOP = new TranAOP();AOP logAOP = new LogAOP();IService service = (IService) new ProxyFactory(teamService, tranAOP).getProxyInstance();IService service1 = (IService) new ProxyFactory(service, logAOP).getProxyInstance();service1.add(); //核心业务+服务代码 混合在一起的完整代码}
方法2: 基于cglib的动态代理
2.1 基础代码
public static void main1(String[] args) {//目标对象:没有接口NBAService nbaService = new NBAService();//cglib代理NBAService proxyService = (NBAService) Enhancer.create(nbaService.getClass(),new MethodInterceptor(){ // 回调函数负责编写代理规则@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {try{System.out.println("事务开始");Object invoke = methodProxy.invokeSuper(o, objects); //最关注的核心的部分System.out.println("事务提交");return invoke;} catch(Exception e) {System.out.println("事务回滚");throw e;} finally{System.out.println("finally----------");}}});//代理对象干活int res = proxyService.add("huren", 1001);System.out.println(res);}
2.2 将回调函数封装
CglibProxyFactory.java
此处事务没有实现接口,而是直接声明了它的Service .
package com.kkb.cglibProxy;import com.kkb.aop.AOP;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxyFactory {//目标对象,没有实现接口private NBAService nbaService;//切面private AOP aop;public Object getProxyInstance(NBAService nbaService, AOP aop){return Enhancer.create(nbaService.getClass(), new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {try{aop.before();Object o1 = methodProxy.invokeSuper(o, objects);aop.after();return o1;} catch(Exception e) {aop.exception();throw e;} finally{aop.myFinally();}}});}}
测试:
public static void main2(String[] args) {NBAService nbaService = new NBAService();AOP tranAop = new TranAOP();NBAService proxyInstance = (NBAService) new CglibProxyFactory().getProxyInstance(nbaService, tranAop);int res = proxyInstance.add("huren", 1001);System.out.println(res);}
