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或者别的版本