Proxy
转载:https://www.cnblogs.com/cenyu/p/6289209.html
代理对象是对目标对象的扩展,并会调用目标对象
1. 静态代理
interface IUserDao(){
void save();
}
public class UserDao implements IUserDao(){
public void save(){
//to save...
}
}
public class UserDaoProxy implements IUserDao(){
private UserDao userDao;
public void save(){
//开始事务
userDao.save();
//提交事务
}
}
缺点: 因为代理类要和目标类实现一样的接口,所以会有很多代理类,一旦接口新增方法,代理类和目标类都要维护。
2. 动态代理(JDK代理)
1. 特点:不需要实现接口,但需要指定接口类型。目标类必须实现接口。
//IUserDao, UserDao 同上
//代理工厂类
public class ProxyFactory{
//目标对象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Obejct getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Obejct[] args) throws Throwable{
//开始事务
//执行目标方法
Object value = method.invoke(target,args);
//提交事务
return value;
}
});
}
}
//测试类
public class Test(){
public static void main(String[] args){
final IUserDao userDao = (IUserDao) new ProxyFactory(new UserDao()).getProxyInstance();
System.out.println("proxy class==" + userDao.getClass());
userDao.save();
}
}
3. cglib代理
- 上面的静态代理和动态代理都需要实现接口。而cglib在内存中构建子类对象从而实现对目标类的代理功能。
- cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类和实现java接口。它广泛的被许多AOP的框架使用。例如Spring aop 和synaop,为他们提供方法的interception(拦截)。
- 实现方法:
- 引入jar包
- 代理的类不能是final
- 目标对象的方法如果是final/static,那就就不会被拦截。
//目标类
public class UserDao(){
public void save(){
//todo
}
}
public class CglibProxyFactory implements MethodInterceptor {
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
//创建代理对象
public Object getProxyInstance() {
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback(this);
//创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//开始事务
System.out.println("---- transaction begin ----");
//执行目标方法
Object value = method.invoke(target, objects);
//提交事务
System.out.println("---- transaction end ----");
return value;
}
}
//测试类
public class Test(){
public static void main(String[] args){
UserDao userDao = (UserDao) new ProxyFactory(new UserDao()).getProxyInstance();
System.out.println("proxy class==" + userDao.getClass());
userDao.save();
}
}