代理模式-- 动态代理
静态代理:要求代理类一定存在,
动态代理:程序运行的时候,根据要被代理的对象动态生成代理类。
类型: 1、基于JDK的动态代理
2、基于CGLIB的动态代理
1 基于JDK的动态代理
静态的,直接用Proxy.调用
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
ClassLoader :类加载器,因为动态代理类,借助别人的类加载器。一般使用被代理对象的
类加载器。
Class[] interfaces:接口类对象的集合,针对接口的代理,针对哪个接口做代理,一般使用的
就是被代理对象的接口。
InvocationHandler:句柄,回调函数,编写代理的规则代码
public Object invoke(Object arg0, Method arg1, Object[] arg2)
Object arg0:代理对象
Method arg1:被代理的方法
Object[] arg2:被代理方法被执行的时候的参数的数组
public class MyJDKProxy {
public static void main(String[] args) {
//目标对象--被代理对象
TeamService teamService=new TeamService();
//返回代理对象
//调用JDK中Proxy类中的静态方法newProxyInstance获取动态代理类的实例
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());
System.out.println(proxyService.getClass()+"--------");
}
}
2 结构化设计
方式1:
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 main2(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()+"------");
}
方式2:
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) {
//目标对象--被代理对象
TeamService 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();
//核心业务+服务代码混合在一起的完整的业务方法
}
代理对象不需实现接口,但目标对象一定要实现接口;否则不能用JDK动态代理 如果想要功能扩展,
但目标对象没有实现接口,怎样功能扩展?
子类的方式实现代理CGLIB。
3 基于CGLIB的动态代理
Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
3.1 测试类
public class NBAService {
public int add(String name,int id){
System.out.println("NBAService---- add----");
return id;
}
}
public static void main(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);
}
3.2 结构化设计方式
public class CglibProxyFactory {
//目标对象
private NBAService nbaService;//没有实现接口的
//切面
private AOP aop;
/**
* 创建代理对象
* @param nbaService
* @param aop
* @return
*/
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 {
System.out.println("finally-----------");
}
}
}
);
}
}
public static void main(String[] args) {
//目标对象:没有接口
NBAService nbaService=new NBAService();
//创建切面
AOP tranAop=new TranAOP();
//创建代理对象:选择cglib动态代理
NBAService proxyInstance = (NBAService)
new CglibProxyFactory().getProxyInstance(nbaService, tranAop);
int res=proxyInstance.add("huren",1001);
System.out.println(res);
}