代理模式:
可以详细控制访问某个类(对象)的方法,在调用这个方法前作的前置处理(统一的流程代码放到代理中处理)。调用这个方法后做后置处理。
例如:老板的秘书,租房的中介等等都是代理
静态代理
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。
package test;
public class StaticProxy {
public static void main(String[] args) {
LiuBoss liuBoss = new LiuBoss();
LiuBossProxy lbp=new LiuBossProxy(liuBoss);
lbp.looA();
lbp.looB();
}
}
interface Boss {
public void looA();
public void looB();
}
class LiuBoss implements Boss{
public void looA(){
System.out.println("LiuBoss looA");
}
public void looB(){
System.out.println("LiuBoss looB");
}
}
class LiuBossProxy implements Boss{
private Boss boss;
public LiuBossProxy(Boss boss){
this.boss=boss;
}
@Override
public void looA() {
System.out.println("------代理类执行之前------");
boss.looA();
System.out.println("------代理类执行之后------");
}
@Override
public void looB() {
System.out.println("------代理类执行之前------");
boss.looB();
System.out.println("------代理类执行之后------");
}
}
动态代理
静态代理有个劣势,每个代理类只能代理一个对象,比如:王老板秘书只能代理王老板,刘老板秘书只能代理刘老板,所以重复了很多代码,这才需要我们使用动态代理,我们只需要一个秘书去代理所有的老板。但是我们开始不知道要找哪个老板实例,所以我们就用到了反射,编译之后我们就知道哪个对象需要被代理了。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DydProxy {
// DydProxy dydProxy=new DydProxy();
public static Object testProxy(final Object tagter){
/*
* 第一个参数:通常与目标对象使用的类加载器一致!
* 第二个参数:通常与目标对象实现的接口一致!(确定实现了哪些接口,就能知道拥有哪些方法)
* 第三个参数:需要实现了 InvocationHandler 实现类的实例(目的执行实现类的 invoke() 方法)
*/
return Proxy.newProxyInstance(tagter.getClass().getClassLoader(), tagter.getClass().getInterfaces(),new InvocationHandler(){
/*
* 生成动态代理:需要实现接口 InvocationHandler
*
* public Object invoke(Object proxy, Method method, Object[] args)
*
* proxy : 生成的代理对象
* method : 代理对象需要执行方法的 Method 实例
* args : 代理对象执行方法所需要的参数
*
*/
//代理方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("------代理类执行之前------");
Object obj = method.invoke(tagter, args);
System.out.println("------代理类执行之后------");
return obj;
}
});
}
}
interface Boss {
public void looA();
public void looB();
}
class LiuBoss implements Boss{
public void looA(){
System.out.println("LiuBoss looA");
}
public void looB(){
System.out.println("LiuBoss looB");
}
}
class WangBoss implements Boss{
public void looA(){
System.out.println("WangBoss looA");
}
public void looB(){
System.out.println("WangBoss looB");
}
private static void looC(){
System.out.println("WangBoss looC");
}
}
public class Demo {
public static void main(String[] args) {
LiuBoss liuBoss=new LiuBoss();
Boss liu = (Boss)DydProxy.testProxy(liuBoss);
liu.looA();
liu.looB();
WangBoss wangBoss=new WangBoss();
Boss wang= (Boss) DydProxy.testProxy(wangBoss);
wang.looA();
wang.looB();
}
}
Cglib代理:
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy {
/**Enhancer增加者*/
private Enhancer en =new Enhancer();
public Object testCglibProxy(Class clazz){
en.setSuperclass(clazz);
/**设置回调*/
en.setCallback(new MethodInterceptor(){
@Override
public Object intercept(Object obj, Method method, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("执行前!!");
Object invoke = proxy.invokeSuper(obj, arg2);
System.out.println("执行后!!");
return invoke;
}
});
/**通过字节码技术动态创建子类实例*/
return en.create();
}
}
class Wang{
public void looA(){
System.out.println("Wang looA!");
}
public void looB(){
System.out.println("Wang looB!");
}
}
class Liu{
public void looA(){
System.out.println("Liu looA!");
}
public void looB(){
System.out.println("Liu looB!");
}
}
public class Demo {
public static void main(String[] args) {
CglibProxy cg=new CglibProxy();
Wang proxy = (Wang) cg.testCglibProxy(Wang.class);
proxy.looA();
}
}