静态代理:使用硬编码的方式,为每个要被代理的方法写一个对应的代理方法:
被代理类:
package red.sea.daelly.proxy.dao.impl;
import red.sea.daelly.proxy.dao.Count;
public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println("查看账户的方法……");
}
@Override
public void updateCount() {
System.out.println("修改账户的方法……");
}
}
代理类:
package red.sea.daelly.proxy.dao.impl;
import red.sea.daelly.proxy.dao.Count;
public class CountProxy implements Count {
//被代理的类
private CountImpl countImpl;
public CountProxy(CountImpl countImpl){
this.countImpl = countImpl;
}
@Override
public void queryCount() {
System.out.println("事物处理前……");
countImpl.queryCount();
System.out.println("事物处理后……");
}
@Override
public void updateCount() {
System.out.println("事物处理前……");
countImpl.updateCount();
System.out.println("事物处理后……");
}
}
这种方式太死板,而且工作量太大。
jdk动态代理:
被代理类:
package red.sea.daelly.proxy.dao;
public interface Bookfacade {
public void addBook();
}
package red.sea.daelly.proxy.dao.impl;
import red.sea.daelly.proxy.dao.Bookfacade;
public class BookfacadeImpl implements Bookfacade {
@Override
public void addBook() {
System.out.println("曾加图书的方法……");
}
}
代理类:
package red.sea.daelly.proxy.dao.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class BookFacadeProxy implements InvocationHandler {
private Object target;
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
System.out.println("事物开始……");
result = method.invoke(target, args);
System.out.println("事物结束……");
return result;
}
}
调用:
package red.sea.daelly.proxy.test;
import red.sea.daelly.proxy.dao.Bookfacade;
import red.sea.daelly.proxy.dao.impl.BookfacadeImpl;
import red.sea.daelly.proxy.dao.proxy.BookFacadeProxy;
/**
* 动态代理的测试类
* @author daelly
*
*/
public class DynamicProxyTest {
public static void main(String[] args){
BookFacadeProxy proxy = new BookFacadeProxy();
Bookfacade bookfacade = (Bookfacade) proxy.bind(new BookfacadeImpl());
bookfacade.addBook();
}
}
这种方式灵活,相同的事物控制代码字需要写一遍就可以了,但是有个小问题,就是被代理的类必须是一个接口的实现。最后介绍的Cglib动态代理方式就不会有这个限制。
cglib动态代理:
被代理类
package red.sea.daelly.cglib.demo;
/**
* 定义一个被代理的类
* @author daelly
*
*/
public class HelloWorld {
public String sayHello(String name){
System.out.println("执行sayHello()");
return "hello,"+name;
}
}
定义一个拦截器:
package red.sea.daelly.cglib.demo;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyMethodInterceptor implements MethodInterceptor {
/**
* obj:代理对象实例
* method:原对象的方法
* args:传递给方法的参数
* proxy:与原对象中method相互对应的代理对象的方法
*/
@Override
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
System.out.println("执行方法"+method+"前");
//这里如果写成invoke(obj, args);就会死循环调用自己,千万记住,我们要调用原方法
Object returnVal = proxy.invokeSuper(obj, args);
System.out.println("执行方法"+method+"后");
return returnVal;
}
}
定义一个创建代理对象的factory方法:
package red.sea.daelly.cglib.demo;
import net.sf.cglib.proxy.Enhancer;
public class ProxyFactory {
public static Object getProxyObj(String classz) throws ClassNotFoundException{
Class<?> superClass = Class.forName(classz);
Enhancer enhancer = new Enhancer();
//设置代理对象的父类
enhancer.setSuperclass(superClass);
//设置回调对象,调用代理对象里面的方法时,实际上执行的是回调对象(里的interept方法)
enhancer.setCallback(new MyMethodInterceptor());
//创建代理对象
return enhancer.create();
}
}
调用测试:
package red.sea.daelly.cglib.demo;
public class CglibDemoTest {
/**
* @param args
*/
public static void main(String[] args) {
try {
//只需要通过类的名字,就能代理之歌方法的执行
HelloWorld hello = (HelloWorld) ProxyFactory.getProxyObj(HelloWorld.class.getName());
String result = hello.sayHello("Cglib");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
三种方式已介绍完