使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过代理类来调用目标方法,代理类会将所有的方法调用分派到目标对象上反射执行,还可以在分派过程中添加"前置通知"和后置处理(如在调用目标方法前校验权限,在调用完目标方法后打印日志等)等功能。
1.静态代理
代理类与被代理类实现同一个接口
在被代理类作为代理类中的属性,重写默认构造器
接口
public interface Count {
// 查看账户方法
public void queryCount();
// 修改账户方法
public void updateCount();
}
被代理类
public class CountImpl implements Count{
public void queryCount() {
System.out.println("查看账户方法...");
}
public void updateCount() {
System.out.println("修改账户方法...");
}
}
代理类
public class CountProxy implements Count {
private CountImpl countImpl;
/**
* 覆盖默认构造器
*
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
}
public void queryCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.queryCount();
System.out.println("事务处理之后");
}
public void updateCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.updateCount();
System.out.println("事务处理之后");
}
}
测试类
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
2.jdk动态代理(实现InvocationHandler接口)
实现原理:JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文件,并加载运行的过程。
Proxy0.class
Proxy0继承Proxy类,并实现UserService接口,在获得代理对象时向上转型,得到UserService 引用。
生成Proxy0.class文件
byte[]classFile =ProxyGenerator.generateProxyClass("Proxy0",BookImpl.class.getInterfaces());
File file =new File("E:/Proxy0.class");
FileOutputStream fos =new FileOutputStream(file);
fos.write(classFile);
fos.flush();
fos.close();
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----------before----------");
Object invoke = method.invoke(target, args);
System.out.println("----------after----------");
return invoke;
}
public Object getProxy(){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),this.target.getClass().getInterfaces(),this);
}
}
接口
public interface UserService{
/**
* 目标方法
*/
public void add(String name);
}
实现类
public class UserServiceImpl implements UserService{
public void add( String name) {
System.out.println("----------add----------");
}
}
测试
public class ProxyTest{
@Test
public void testProxy() throws Throwable{
//实例化目标对象
UserService userService=new UserServiceImpl();
//实例化Invocation
MyInvocationHandler invocationHandler=new MyInvocationHandler(userService);
//根据目标生成代理对象
UserService proxy=(UserService)invocationHandler.getProxy();
//调用代理对象方法
proxy.add("-----------------------><--------------------------------");
}
}
3.cglib代理
cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理
定义代理实现 MethodInterceptor接口
被代理类
public class BookFacadeImpl {
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
代理类
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
测试
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());
bookCglib.addBook();
}
}