静态代理
定义一个接口
/**
* 定义一个账户接口
*
* @author Administrator
*
*/
public interface Count {
// 查看账户方法
public void queryCount();
// 修改账户方法
public void updateCount();
}
接口实现类
public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println("查看账户方法...");
}
@Override
public void updateCount() {
System.out.println("修改账户方法...");
}
}
接口实现代理类
/**
* 这是一个代理类(增强CountImpl实现类)
*
* @author Administrator
*
*/
public class CountProxy implements Count {
private CountImpl countImpl;
/**
* 覆盖默认构造器
*
* @param 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("事务处理之后");
}
}
运行
public class CountTest {
/**
* @param args
*/
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
从静态代理中可以看出:
1.接口:代理类需要实现一个接口,这个接口和委托类的接口是一样的,这样proxy才能和委托类行为表现一致
2. 方法(Method):由于接口限制,proxy类中也要有interface中的各个方法,这就造成了代码重复
JDK动态代理
接口
public interface Hello {
public void sayHello(String name);
}
接口实现
public class HelloImpl implements Hello {
public void sayHello(String name) {
System.out.println("Hello ,"+name);
}
}
代理类
public class JDKDyProxy implements InvocationHandler {
private Object target;
public JDKDyProxy(Object target) {
this.target = target;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before(){
System.out.println("before");
}
private void after(){
System.out.println("after");
}
}
运行
public class Test1 {
public static void main(String[] args) {
Hello helloProxy = new HelloImpl();
JDKDyProxy jdkDyProxy = new JDKDyProxy(helloProxy);
Hello proxy = jdkDyProxy.getProxy();
proxy.sayHello("fsdafd");
}
}
JDK代理要有接口的类才可以,没的接口的类是不能代理的
CGLib动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
代理类
public class CGLibProxy implements MethodInterceptor{
private static final CGLibProxy instance = new CGLibProxy();
private CGLibProxy() {
}
public static CGLibProxy getInstance() {
return instance;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> cls){
return (T)Enhancer.create(cls, this);
}
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
Object result =proxy.invokeSuper(obj, args);
after();
return result;
}
private void after() {
System.out.println("after");
}
private void before() {
System.out.println("before");
}
}
运行
public static void main(String[] args) {
/*Hello helloProxy = new HelloImpl();
JDKDyProxy jdkDyProxy = new JDKDyProxy(helloProxy);
Hello proxy = jdkDyProxy.getProxy();
proxy.sayHello("fsdafd");*/
Hello proxy = CGLibProxy.getInstance().getProxy(HelloImpl.class);
proxy.sayHello("ppp");
}
CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,
但是CGLib在创建代理对象时所花费的时间却比JDK多得多,
所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,
反之,使用JDK方式要更为合适一些。
同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。