对代理模式的解读和实现
什么是代理模式
代理:自己不做,找人帮你做。
代理模式:在一个原有功能的基础上添加新的功能。
分类:静态代理和动态代理。
静态代理
代理类由程序员自己编写(代理类会对目标对象的特定方法进行增强)
基本步骤
1、设计接口:代理对象和目标对象都实现同一个功能。
2、编写目标对象(类):实现接口
3、编写代理对象(类):实现接口,注入目标对象,调用其方法,最后增强方法。
实现
原有方式:核心业务和服务方法都编写在一起
public class TeamService {
public void add(){
try {
System.out.println("开始事务");
System.out.println("TeamService---- add----");// 核心业务
System.out.println("提交事务");
} catch (Exception e) {
e.printStackTrace();
System.out.println("回滚事务");
}
}
}
代理方式实现:
/**
* 切面:服务代码,切入到核心代码中,切入到哪里,给了四个位置
*/
public interface AOP {
void before();
void after();
void exception();
void myFinally();
}
public class TranAOP implements AOP {
@Override
public void before() {
System.out.println("事务----before");
}
@Override
public void after() {
System.out.println("事务----after");
}
@Override
public void exception() {
System.out.println("事务----exception");
}
@Override
public void myFinally() {
System.out.println("事务----myFinally");
}
}
public class LogAop implements AOP{
@Override
public void before() {
System.out.println("日志----before");
}
@Override
public void after() {
System.out.println("日志----after");
}
@Override
public void exception() {
System.out.println("日志----exception");
}
@Override
public void myFinally() {
System.out.println("日志----myFinally");
}
}
public class ProxyAOPService implements IService {
private IService service;//被代理对象
private AOP aop;//要加入切面
public ProxyAOPService(IService service, AOP aop) {
this.service = service;
this.aop = aop;
}
@Override
public void add() {
try {
aop.before();
service.add();//被代理对象干活
aop.after();
}catch (Exception e){
aop.exception();
}finally {
aop.myFinally();
}
}
}
@Test
public void test02(){
IService teamService=new TeamService();//被代理对象--核心内容
AOP logAop=new LogAop();//切面-服务内容
AOP tranAop=new TranAOP();
IService service=new ProxyAOPService(teamService,logAop); //代理对象--一级代理
IService service2=new ProxyAOPService(service,tranAop);//代理对象--二级代理
service2.add();
}
总结
1)可以做到在不修改目标对象的功能前提下,对目标对象功能扩展。
2)缺点:
因为代理对象,需要与目标对象实现一样的接口。所以会有很多代理类,类太多。
一旦接口增加方法,目标对象与代理对象都要维护。
每次编写一个目标类的时候,都需要重新去编写(至少)一个代理类,太麻烦了,因此我们希望系统可以自动生成代理对象,即动态代理。
动态代理
静态代理:要求代理类一定存在,
动态代理:程序运行的时候,根据要被代理的对象动态生成代理类。
类型:
1、基于JDK的动态代理
2、基于CGLIB的动态代理
基于JDK的动态代理
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。
基于CGLIB的动态代理
Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
- JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。
- CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception。
- CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
核心方法功能
Enhancer:核心类,提供目标对象的子类对象(代理对象)
create():提供代理对象
MethodInterceptor:接口
intercept:抽象方法,对目标对象方法的增强
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);
}