校园网站建设情况通报,网站建设培训会上的讲话,企业展厅设计设计公司,营销型网站建设设计代理模式就是给一个对象提供一个代理对象#xff0c;让该代理对象来控制对原对象的引用#xff0c;比如买车去4s店#xff0c;而不是去汽车厂#xff0c;4s就起到一个代理的作用。
1.静态代理 代理类实现一个接口#xff0c;之后实现该接口的其他类就可在该代理类中被增强… 代理模式就是给一个对象提供一个代理对象让该代理对象来控制对原对象的引用比如买车去4s店而不是去汽车厂4s就起到一个代理的作用。
1.静态代理 代理类实现一个接口之后实现该接口的其他类就可在该代理类中被增强具有通用性。 如下
/*抽象用户操作定义*/
public interface UserDao {void saveUser();}
/*普通用户实现类*/
public class UserDaoImpl implements UserDao {Overridepublic void saveUser() {System.out.println(普通用户实现);}}
/*静态代理类*/
public class StaticProxy implements UserDao{UserDao userDao;public StaticProxy(UserDao userDao) {this.userDao userDao;}Overridepublic void saveUser() {System.out.println(保存日志);try {userDao.saveUser();}catch (Exception e){System.out.println(保存日志);}finally {System.out.println(保存日志);}System.out.println(保存日志);}}
public class Test {public static void main(String[] args) {//具体对象UserDao userDao new UserDaoImpl();StaticProxy staticProxy new StaticProxy(userDao);staticProxy.saveUser();}
} 创建静态代理类的对象将我们创建的普通对象作为参数传入之后调用代理类中的saveUser()方法就起到了增强的作用缺点就是一个代理类只能代理一个接口而且接口如果有所修改代理类也要同步修改。
2.动态代理
2.1JDK代理 JDK代理是通过反射来获取代理对象的通过reflect.Proxy来实现通过固定的规则生成。如下
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*动态代理类代理类不需要实现与目标类相同的接口,这样就可以代理任意的目标类但是是有要求的,目标类必需实现接口,此种方式是动态代理的实现方式之一: jdk代理 是一种纯反射机制实现(动态获取目标类接口方法)*/
public class DynamicProxy implements InvocationHandler {Object object;//真实对象,接收任何的目标类对象public DynamicProxy(Object object) {this.object object;}/*在代理类中调用目标类中的具体方法,动态的将代理动态对象,目标类中要调用的方法,及方法中的参数传递过来Method method 就是动态获取的真正要执行的方法*/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(之前开启事务);method.invoke(object);System.out.println(之后提交事务);return proxy;}//真正意义上,运行时生成代理对象的方法需要被代理类的类加载器类实现的接口public Object getProxy(){return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);}}
public class Test {public static void main(String[] args) {UserDaoImpl userDao new UserDaoImpl();DynamicProxy dtproxy new DynamicProxy(userDao);//自己创建的代理类对象//这才是真正的创建动态代理对象UserDao userDao (UserDao)dtproxy.getProxy();userDao.saveUser();//使用代理对象调用接口中的方法,获取当前调用的方法,最终调用invoke方法}
} JDK代理的致命缺陷就是被代理的目标类必须实现接口。
2.2Cglib代理 Cglib代理很好的解决了目标类无接口实现的情况Cglib底层采用了字节码的方式给目标类创建了一个子类在子类中采用方法拦截的方式拦截父类的方法调用然后使用横切的思想去增强。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** 动态代理类*/
public class CGLibProxy implements MethodInterceptor {private Enhancer enhancer new Enhancer();public Object getProxy(Class? clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } /** 拦截所有目标类方法的调用 * 参数 * obj 目标实例对象 * method 目标方法的反射对象 * args 方法的参数 * proxy 代理类的实例 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {//代理类调用父类的方法 System.out.println(开始事务); Object obj1 proxy.invokeSuper(obj, args); System.out.println(关闭事务); return obj1; }
} public class Test {public static void main(String[] args) {CGLibProxy proxy new CGLibProxy(); UserDaoImpl userDaoImpl (UserDaoImpl)proxy.getProxy(UserDaoImpl.class);userDaoImpl.save();}
} 需要注意的是如果使用Cglib代理那么目标类不能被final修饰目标类中的方法不能被final或static修饰虽然Cglib方式创建的代理对象性能功能比JDK方式创建的代理对象性能好但是相应的花费的时间也多所以对于单例的Cglib方式比较合适。