一、代理模式的介绍
代理模式,是指对一个对象提供一种代理以控制对这个对象的访问。使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。
客户类真正想访问的是目标对象,但客户类可以访问的对象是代理对象。可以以“代理律师”来理解“代理模式”。
二、包的命名
JAVA中包的命名一般分为4-5层:
1、甲方公司域名的倒叙 com.jmu
2、项目名称 oa
3、模块信息 xxx
4、功能顶层包 service、dao、beans、vo
5、实现类 (有些功能包没有实现类) impl
例: com.jmu.oa.xxx.dao.impl
之所以要这样命名项目中的包,是为了保证项目中所用到的类具有全球唯一性。
实体
beans、entity、持久化对象po(Persistance Object)
以上包中所存放的类,数据库中有其对应的表,一般有id 属性。
vo:Value Object,值对象。一般用于类和页面之间传值
dto:Data Transter Object, 数据传输对象,一般用于类间传值。
以上包中所存放的类,数据库中没有其对应的表,用于类和类之间、类和对象之间传值,一般没有id属性。因为它们不需要持久化。仅仅是用于在代码中进行数据传递。
dao: Data Access Object 数据访问对象,增删改查
三、代理环境的搭建
public interface ISomeService { String doFirst(); void doSecond(); }
public class SomeServiceImpl implements ISomeService{ @Override public String doFirst() { // TODO Auto-generated method stub System.out.println("执行doFirst()方法"); return "abcde"; } @Override public void doSecond() { // TODO Auto-generated method stub System.out.println("执行doSecond()方法"); } }
1 public class MyTest { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 ISomeService service=new SomeServiceImpl(); 6 String result =service.doFirst(); 7 System.out.println("result="+result); 8 service.doSecond(); 9 } 10 11 }
输出:
执行doFirst()方法 result=abcde 执行doSecond()方法
四、静态代理的实现
静态代理:代理类在程序运行前已经定义好,其与目标类的关系在程序运行前已经确立。
案例要求:
要求输出大写的ABCD
1 import com.jmu.service.ISomeService; 2 import com.jmu.serviceImpl.SomeServiceImpl; 3 //代理类 4 public class SomeServiceProxy implements ISomeService{ 5 6 private ISomeService target; 7 8 public SomeServiceProxy() { 9 target = new SomeServiceImpl(); 10 } 11 12 @Override 13 public String doFirst() { 14 //代理类调用目标方法 15 String result=target.doFirst(); 16 //增强 17 return result.toUpperCase(); 18 } 19 20 @Override 21 public void doSecond() { 22 // TODO Auto-generated method stub 23 target.doSecond(); 24 } 25 26 }
输出:
执行doFirst()方法 result=ABCDE 执行doSecond()方法
(视频中的理解图)
五、动态代理
1、JDK动态代理
使用JDK的Proxy动态代理,要求目标类必须实现接口,因为其底层的实现原理和静态代理一样。
在之前基础上删除 SomeServiceProxy类,然后
1 import java.lang.reflect.InvocationHandler; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.Proxy; 4 5 import com.jmu.service.ISomeService; 6 import com.jmu.serviceImpl.SomeServiceImpl; 7 8 public class MyTest { 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 ISomeService target=new SomeServiceImpl(); 13 ISomeService service=(ISomeService) Proxy.newProxyInstance( 14 target.getClass().getClassLoader(),//目标类的类加载器 15 target.getClass().getInterfaces(), //目标类所实现的所有接口 16 new InvocationHandler() { //匿名内部类 17 //proxy:代理对象 18 //method:目标对象 19 //args:目标对象的参数列表 20 @Override 21 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 22 // TODO Auto-generated method stub 23 //调用目标方法 24 Object result = method.invoke(target, args); 25 26 if (result!=null) { 27 result = ((String) result).toUpperCase(); 28 } 29 return result; 30 } 31 }); 32 String result =service.doFirst(); 33 System.out.println("result="+result); 34 service.doSecond(); 35 } 36 37 }
2、CGLIB动态代理
对于无接口的类,要为其创建动态代理,就要用CGLIB来实现。CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类能被继承,不能是final的类。
对于有接口的类,以为其有子类,所以也会有CGLIB动态代理。
首先,添加cglib包
还涉及方法回调设计模式
(1)无接口
public class SomeService { public String doFirst() { // TODO Auto-generated method stub System.out.println("执行doFirst()方法"); return "abcde"; } public void doSecond() { // TODO Auto-generated method stub System.out.println("执行doSecond()方法"); } }
1 package com.jmu.factory; 2 3 import java.lang.reflect.Method; 4 5 import com.jmu.service.SomeService; 6 7 import net.sf.cglib.proxy.Enhancer; 8 import net.sf.cglib.proxy.MethodInterceptor; 9 import net.sf.cglib.proxy.MethodProxy; 10 11 public class MyCglibFactory implements MethodInterceptor { 12 private SomeService target; 13 14 public MyCglibFactory() { 15 target = new SomeService(); 16 } 17 18 public SomeService myCglibCreator() { 19 // 创建增强器对象 20 Enhancer enhancer = new Enhancer(); 21 // 指定目标类,即父类 22 enhancer.setSuperclass(SomeService.class); 23 // 设置回调接口对象 24 enhancer.setCallback(this); 25 return (SomeService) enhancer.create(); 26 } 27 28 // 回调方法 29 @Override 30 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 31 Object result = method.invoke(target, args); 32 33 if (result!=null) { 34 result = ((String) result).toUpperCase(); 35 } 36 return result; 37 } 38 }
1 package com.jmu.test; 2 3 import com.jmu.factory.MyCglibFactory; 4 import com.jmu.service.SomeService; 5 6 public class MyTest { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 SomeService service=new MyCglibFactory().myCglibCreator(); 11 String result =service.doFirst(); 12 System.out.println("result="+result); 13 service.doSecond(); 14 } 15 16 }
(2)有接口
1 package com.jmu.service; 2 //业务接口 3 public interface ISomeService { 4 //目标方法 5 String doFirst(); 6 void doSecond(); 7 }
1 package com.jmu.service; 2 3 import com.jmu.service.ISomeService; 4 //目标类 5 public class SomeServiceImpl implements ISomeService{ 6 7 @Override 8 public String doFirst() { 9 // TODO Auto-generated method stub 10 System.out.println("执行doFirst()方法"); 11 return "abcde"; 12 } 13 14 @Override 15 public void doSecond() { 16 // TODO Auto-generated method stub 17 System.out.println("执行doSecond()方法"); 18 19 } 20 21 }
1 package com.jmu.factory; 2 3 import java.lang.reflect.Method; 4 5 import com.jmu.service.ISomeService; 6 import com.jmu.service.SomeServiceImpl; 7 8 import net.sf.cglib.proxy.Enhancer; 9 import net.sf.cglib.proxy.MethodInterceptor; 10 import net.sf.cglib.proxy.MethodProxy; 11 12 public class MyCglibFactory implements MethodInterceptor { 13 private ISomeService target; 14 15 public MyCglibFactory() { 16 target = new SomeServiceImpl(); 17 } 18 19 public ISomeService myCglibCreator() { 20 // 创建增强器对象 21 Enhancer enhancer = new Enhancer(); 22 // 指定目标类,即父类 23 enhancer.setSuperclass(ISomeService.class); 24 // 设置回调接口对象 25 enhancer.setCallback(this); 26 return (ISomeService) enhancer.create(); 27 } 28 29 // 回调方法 30 @Override 31 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 32 Object result = method.invoke(target, args); 33 34 if (result!=null) { 35 result = ((String) result).toUpperCase(); 36 } 37 return result; 38 } 39 }
1 package com.jmu.test; 2 3 import com.jmu.factory.MyCglibFactory; 4 import com.jmu.service.ISomeService; 5 6 public class MyTest { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 ISomeService service=new MyCglibFactory().myCglibCreator(); 11 String result =service.doFirst(); 12 System.out.println("result="+result); 13 service.doSecond(); 14 } 15 16 }