一:静态代理
首先要定义一个公共的接口,供代理类和被代理类实现,供代理类有增强点
package cn.com.staticProxy;
/**
* *
*<p>Title: IUserDao</p>
* <p>Description:公共的接口</p>
* <p>Company: </p>
* @author Administrator
* @date 2019年4月24日 下午4:15:12
*/
public interface IUserDao {
void save();
void find();
}
被代理类:
package cn.com.staticProxy;
public class UserDao implements IUserDao{
/**
* 被代理类或者叫代理目标类
*/
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("模拟保存用户");
}
@Override
public void find() {
// TODO Auto-generated method stub
System.out.println("模拟查找用户");
}
}
对比一下直接调用:
package cn.com.staticProxy;
/**
* *
*<p>Title: Test2</p>
* <p>Description:直接使用被代理类 </p>
* <p>Company: </p>
* @author Administrator
* @date 2019年4月24日 下午4:18:39
*/
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
IUserDao udp=new UserDao();
udp.save();
System.out.println("-------------------");
udp.find();
}
}
结果:
模拟保存用户
-------------------
模拟查找用户
代理类:
package cn.com.staticProxy;
public class UserDaoProxy implements IUserDao {
private UserDao ud = new UserDao();
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("代理操作,开启事务");
ud.save();
System.out.println("代理操作,关闭事务");
}
@Override
public void find() {
// TODO Auto-generated method stub
System.out.println("代理操作,开启事务");
ud.find();
System.out.println("代理操作,关闭事务");
}
}
代理类调用:
package cn.com.staticProxy;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
IUserDao udp=new UserDaoProxy();//不是直接new UserDao对象,而是通过代理类创建对象。因为都实现了IUserDao接口
udp.save();
System.out.println("-------------------");
udp.find();
}
}
结果:
代理操作,开启事务
模拟保存用户
代理操作,关闭事务
-------------------
代理操作,开启事务
模拟查找用户
代理操作,关闭事务
二、JDK动态代理
沿用上面的例子
JDK的动态代理存在不足,即被代理类必须要有实现的接口,如没有接口则无法使用JDK动态代理
package cn.com.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import cn.com.staticProxy.IUserDao;
import cn.com.staticProxy.UserDao;
public class DynamicProxy implements InvocationHandler{
//被代理类的实例
private IUserDao iud=null;//接口不能实例化,但可以进行申明
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result=null;
System.out.println("开始JDK动态代理");
method.invoke(iud, args);
System.out.println("结束JDK动态代理");
return result;
}
//构造方法
public DynamicProxy(IUserDao iud){
this.iud=iud;
}
}
需要实现JDK中的InvocationHandler接口,实现其中的invoke方法,在此方法中通过反射的方式调用被代理类的方法,可以在方法执行前或后进行别的处理,下面看测试代码:
package cn.com.dynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.com.staticProxy.IUserDao;
import cn.com.staticProxy.UserDao;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserDao ud=new UserDao();
DynamicProxy dp=new DynamicProxy(ud);
//动态生成代理对象,不像静态代理需要提前代理,而是在需要是调用Proxy.newProxyInstance生成代理对象
//ud.getClass().getClassLoader()是通过反射获取ud的构造器,(用哪个类加载器去加载代理对象)
//ud.getClass().getInterfaces()获得ud的所有接口,也就获得了需要被代理的方法,因为实体类要实现这些方法(动态代理类需要实现的接口)
//dp(动态代理方法在执行时,会调用dp里面的invoke方法去执行),这个类必须是实现了InvocationHandler接口的
IUserDao iud=(IUserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), dp);
iud.save();
System.out.println("--------------");
iud.find();
}
}
三、cglib动态代理
需要引入CGLib的jar包
要使用CGLib代理需要实现其MethodInterceptor接口:
package cn.com.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println("开始CGLib动态代理");
Object object=proxy.invokeSuper(obj, args);
System.out.println("结束CGLib动态代理");
return object;
}
}
测试代码:
package cn.com.cglib;
import cn.com.staticProxy.UserDao;
import net.sf.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(UserDao.class);
enhancer.setCallback(new MyMethodInterceptor());
//生成代理类
UserDao ud=(UserDao) enhancer.create();
ud.save(); System.out.println("----------------");
ud.find();
}
}