案例需求:需要在原来的dao实现类的方法中,加入日志的记录功能,对原有的功能进行增强
1. 静态代理
静态代理的组成:
抽象接口:目标类和代理类必须实现同一个抽象接口。
目标类:封装了原始的核心功能
代理类:拥有目标对象的引用,同时完成扩展功能的实现
总结:将核心功能和扩展功能在代码的实现上,进行了分离在使用的时候将分离实现的功能进行合并。
应用场景:对系统中原有的功能进行升级(可以不修改源码 )
系统中如果分散着一些共性的,公共功能的代码(将这样功能的代码抽取进行单独的开发)
2. 动态代理
动态代理的实现原理:
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
2.1动态代理实现的API
Proxy
提供用于创建动态代理类和实例的静态方法
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
InvocationHandler 是代理实例的调用处理程序 实现的接口
当使用代理类的对象调用某个方法的时候 ,该方法的执行会被InvocationHandler对象拦截
Object invoke(Object proxy, Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
2.2 创建Dao接口
1 public interface Dao
2 {
3 public String save(String uname);
4 public String delete(Integer id);
5 }
2.3 创建实现类
1 public class DaoImpl implements Dao
2 {
3 @Override
4 public String save(String uname)
5 {
6 /**
7 * code....
8 * **/
9 System.out.println("----------数据保存到数据库---------");
10 return "hello " + uname;
11 }
12
13 @Override
14 public String delete(Integer id)
15 {
16 // TODO Auto-generated method stub
17 System.out.println("----------数据库删除操作------------");
18 return "id=" + id;
19 }
20 }
2.4创建工具类
产生代理对象
1 public class GetProxyInstance
2 {
3 private Object target; // 目标对象
4
5 public GetProxyInstance()
6 {
7 }
8
9 public GetProxyInstance(Object target)
10 {
11 this.target = target;
12 }
13
14 public Object getProxyInstance()
15 {
16 System.out.println("----------getProxyInstance");
17 return Proxy.newProxyInstance(GetProxyInstance.class.getClassLoader(),// 类加载器对象
18 new Class[]
19 { Dao.class },// 代理对象需要实现的接口
20 new MyInvocationHandler());// 代理对象调用的方法对应的处理器
21 }
22
23 // 代理对象调用的方法对应的处理器类
24 class MyInvocationHandler implements InvocationHandler
25 {
26 @Override
27 public Object invoke(Object proxy, // 代理对象
28 Method method, // 被拦截到的方法
29 Object[] args) // 拦截的方法执行需要的参数
30 throws Throwable
31 {
32 // TODO Auto-generated method stub
33 String methodName = method.getName();// 获得方法的名称
34 // System.out.println(methodName+"--------"+Arrays.toString(args));
35 if (methodName.equals("save"))
36 {
37 System.out.println("-------完成日志的记录----------" + new Date()
38 + "----" + Arrays.toString(args));
39 }
40 // 通过反射完成方法的调用:完成目标对象方法的调用,放行
41 Object rv = method.invoke(target, args);
42 //
43 return rv;
44 }
45 }
46 }
2.5 创建测试类
1 public class TestProxy
2 {
3 public static void main(String[] args)
4 {
5 // 创建GetProxyInstance对象,传入被代理的目标对象
6 GetProxyInstance gpi = new GetProxyInstance(new DaoImpl());
7 // 获得代理对象
8 Object obj = gpi.getProxyInstance();
9 // System.out.println(obj instanceof Dao);
10 // 向下转型
11 Dao dao = (Dao) obj;
12 String result = dao.save("乌龟");
13 String result2 = dao.delete(100);
14 // System.out.println("======"+result);
15 System.out.println(dao.getClass());
16 new DaoImpl().save("王八");
17 }
18 }