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{
@Override
public void before() {
System.out.println("日志------before------");
}
@Override
public void exception() {
System.out.println("日志------exception------");
}
@Override
public void after() {
System.out.println("日志------after------");
}
@Override
public void myFinally() {
System.out.println("日志------finally------");
}
}
TranAOP.java
package com.kkb.aop;
public class TranAOP implements AOP {
@Override
public void before() {
System.out.println("事务-----before-----");
}
@Override
public void exception() {
System.out.println("事务-----exception-----");
}
@Override
public void after() {
System.out.println("事务-----after-----");
}
@Override
public 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{
@Override
public 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() { //回调函数,编写代理规则
@Override
public 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()); //静态代理,地址为我们自己构建的TeamService
System.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;
}
@Override
public 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() { //回调函数,编写代理规则
@Override
public 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(){ // 回调函数负责编写代理规则
@Override
public 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() {
@Override
public 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);
}