Java代理机制 分类:
静态代理:继承代理【基于抽象类的代理】
聚合代理【基于接口的代理】
动态代理:jdk代理【只针对接口,不能针对类】
cglib代理【针对类实现代理,主要对指定的类产生一个子类,并且覆盖其中的方法实现类增强,因为采取的是继承的方式,无法对final类进行代理,hibernate使用的是cglib代理】
1. 聚合代理
package proxy2; /** ************************************* * @Title Movable.java * @Author 张作强 * @Date 2010-8-22 * @Comment 聚合代理是基于接口的代理,先声明接口 ************************************* */ public interface Movable { void move(); }
package proxy2; import java.util.Random; /** ************************************* * @Title Tank.java * @Author 张作强 * @Date 2010-8-22 * @Comment 被代理的实体类,实现接口 ************************************* */ public class Tank implements Movable { public void move() { long begin=System.currentTimeMillis(); System.out.println("Tank Moving"); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } long end=System.currentTimeMillis(); System.out.println("Tank Move :"+(end-begin)); } }
package proxy2; /** ************************************* * @Title TankTranProxy.java * @Author 张作强 * @Date 2010-8-22 * @Comment 代理的实现1,在调用被代理类的方法前后实现事物操作 ************************************* */ public class TankTranProxy implements Movable { Movable tank; //实现接口 public void move() { System.out.println("Begin Transaction...."); //这里调用的是构造函数传递过来的实现了接口的类 tank.move(); System.out.println("End Transaction...."); } //构造函数,将实现接口的对象作为参数传递给构造函数 public TankTranProxy(Movable tank) { super(); this.tank = tank; } }
package proxy2; /** ************************************* * @Title TankLogProxy.java * @Author 张作强 * @Date 2010-8-22 * @Comment 代理的实现2,在调用被代理类的方法前后实现日志操作 ************************************* */ public class TankLogProxy implements Movable { Movable t; public TankLogProxy(Movable m) { super(); this.t = m; } public void move() { System.out.println("Loging...."); t.move(); System.out.println("End Loging....."); } }
package proxy2; public class TestMain { public static void main(String[] args) { Tank tank=new Tank(); //在执行被代理类之前先进行事务操作 Movable tankTran=new TankTranProxy(tank); //在执行被代理类之前先进行日志操作 Movable tankLog=new TankLogProxy(tankTran); //注:也可以把以上两行代码反过来些,就在执行被代理类之前先执行日志操作,然后进行事务操作 //然后再执行被代理类的方法 tankLog.move(); } }
结果:
Loging....
Begin Transaction....
Tank Moving
Tank Move :8375
End Transaction....
End Loging.....
2. 继承代理
package proxy3; //被代理的类 public abstract class Tank { public void move(){ System.out.println("Tank Moving... "); } }
package proxy3; public class TankProxy extends Tank { //以继承的方式实现代理 //重写父类的方法 public void move(){ long start = System.currentTimeMillis(); System.out.println("Before Moving:" + start); //注:该处调用的是Tank类的move,所以是代理Tank类的方法 super.move(); long end = System.currentTimeMillis(); System.out.println("After Moving:" + end); System.out.println("您共运行了:" + (start - end) + "毫秒"); } }
package proxy3; public class Test { public static void main(String[] args) { TankProxy tankProxy = new TankProxy(); tankProxy.move(); } }
结果:
Before Moving:1282459642796
Tank Moving...
After Moving:1282459642796
您共运行了:0毫秒
3. jdk动态代理
package proxy4; // jdk动态代理是基于接口实现的,第一步,先定义接口 public interface UserManager { void save(String name,String password); void delUser(int id); }
package proxy4; //被代理的类实现接口 public class UserManagerImpl implements UserManager { public void save(String name, String password) { System.out.println("UserManagerImpl.save..用户名:" + name + "用户密码:" + password); } public void delUser(int id) { System.out.println("UserManagerImpl.delUser..用户ID:"+id ); } }
package proxy4; //在执行被代理类的方法时,插入安全检查的类 public class Security { public void securityCheck(){ System.out.println("security Checking..."); } }
package proxy4; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class UserManagerProxy implements InvocationHandler { UserManager userManager; //生成代理类 public Object getUserManagerProxy(UserManager userManager){ this.userManager = userManager; return Proxy.newProxyInstance(userManager.getClass().getClassLoader(), userManager.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("----------------- 参数列表 -----------------"); for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } System.out.println("----------------- 调用的方法 -----------------"); System.out.println(method.getName()); System.out.println("----------------- 安全检查 -----------------"); Security security = new Security(); security.securityCheck(); System.out.println("----------------- 执行方法 -----------------"); Object object=method.invoke(userManager, args); System.out.println("\n--------------------------------—-------\n"); return object; } }
package proxy4; public class Test { public static void main(String[] args) { //这里必须使用接口进行类型转换 UserManager userManager=(UserManager)new UserManagerProxy(). getUserManagerProxy(new UserManagerImpl()); userManager.save("张三","123456"); userManager.delUser(3); } }
结果:
----------------- 参数列表 -----------------
张三
123456
----------------- 调用的方法 -----------------
save
----------------- 安全检查 -----------------
security Checking...
----------------- 执行方法 -----------------
UserManagerImpl.save..用户名:张三用户密码:123456
--------------------------------—-------
----------------- 参数列表 -----------------
3
----------------- 调用的方法 -----------------
delUser
----------------- 安全检查 -----------------
security Checking...
----------------- 执行方法 -----------------
UserManagerImpl.delUser..用户ID:3
--------------------------------—-------
4. cglib动态代理
cglib代理必须先引入包:cglib.jar或者别的版本