当前位置: 首页 > news >正文

买完阿里云域名如何做网站广告软文小故事200字

买完阿里云域名如何做网站,广告软文小故事200字,开源crm客户管理系统,学校网站建设策划书1、什么是动态代理 可能很多小伙伴首次接触动态代理这个名词的时候,或者是在面试过程中被问到动态代理的时候,不能很好的描述出来,动态代理到底是个什么高大上的技术。不方,其实动态代理的使用非常广泛,例如我们平常使…

1、什么是动态代理

可能很多小伙伴首次接触动态代理这个名词的时候,或者是在面试过程中被问到动态代理的时候,不能很好的描述出来,动态代理到底是个什么高大上的技术。不方,其实动态代理的使用非常广泛,例如我们平常使用的 Spring中的 @Transactional注解,其依赖于 AOP,而 AOP的底层实现便是动态代理,看到这里,是不是更有兴趣去了解动态代理了呢?

动态代理:可以分解为"动态"+“代理”。

  • 代理:"代理"一词,在我们的生活中也是随处可见的,例如房屋中介,其是对房主的一种代理,房主需要出租其房屋,但是可能没时间去接待租客,给租客介绍房屋信息,带领租客看房,但是房屋中介可以为租客提供这些服务,所以,代理其是对被代理对象的一个功能增强
  • 动态:"动态"通常与"静态"相比较,"静态"描述的是事物是固定存在的,"动态"则描述的是事物是随着需求而动态生成的。

所以,静态代理存在一定的局限性,不能很好的满足需求的千变万化,动态代理的出现,就是为了解决这些局限性。

我们先来看看静态代理。

2.、静态代理

在开发中,通常需要为方法添加日志打印,能够记录程序的执行过程,以便后续出现异常问题的时候,能更好的排查定位。

假设我们现在已经完成了系统用户的增加、删除、修改等功能,这些功能在类 UserServiceImpl中已经实现。

代码示例:

public class UserServiceImpl {public void add() {System.out.println("添加用户");}public void update() {System.out.println("修改用户");}public void delete() {System.out.println("删除用户");}
}

现在,我们需要在UserServiceImpl类中的方法添加日志功能,那么怎么才能更好地去实现这个需求呢?

1)直接在目标方法前后添加日志代码

代码示例:

public class UserServiceImpl {public void add() {System.out.println("====== add方法开始 ======");System.out.println("添加用户");System.out.println("====== add方法结束 ======");}public void update() {System.out.println("====== update方法开始 ======");System.out.println("修改用户");System.out.println("====== update方法结束 ======");}public void delete() {System.out.println("====== delete方法开始 ======");System.out.println("删除用户");System.out.println("====== delete方法结束 ======");}
}

观察上述代码,这种方式的缺点在于:

2)静态代理方式实现

静态代理需要我们将目标类的方法抽取到接口中,代理类和目标类实现同一个接口,既然要实现代理,代理类自然需要在其内部维护目标对象的引用,并通过构造函数为其赋值,然后在代理类的方法中调用目标对象的同名方法,并在调用前后完成功能的增强。

实现步骤:

  • 抽取UserService接口
  • 创建目标类UserServiceImpl实现UserService接口
  • 创建代理类UserServiceProxy实现UserService接口
  • 代理类中完成功能的增强

代码实现:

// 目标接口
public interface UserService {void add();void update();void delete();
}
// 目标类
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("添加用户");}@Overridepublic void update() {System.out.println("修改用户");}@Overridepublic void delete() {System.out.println("删除用户");}
}
// 代理类
public class UserServiceProxy implements UserService {private UserService userService;public UserServiceProxy(UserService userService) {this.userService = userService;}@Overridepublic void add() {System.out.println("====== add方法开始 ======");userService.add();System.out.println("====== add方法结束 ======");}@Overridepublic void update() {System.out.println("====== update方法开始 ======");userService.update();System.out.println("====== update方法结束 ======");}@Overridepublic void delete() {System.out.println("====== delete方法开始 ======");userService.delete();System.out.println("====== delete方法结束 ======");}
}

观察上述代码,静态代理遵循开闭原则,在不修改目标类的前提下,完成了功能的增强,但是依然存在大量重复的代码,且一个代理类只能代理一个目标类,如果有n个目标类需要被代理,就需要同比增加n个代理类。

那么,有没有办法可以使得我们不需要去定义这么多的代理类,就可以实现对目标类功能的增强?答案是有的:动态代理

3、JDK动态代理

前面,我们提到静态代理的实现方式:代理类和目标类都实现同一个接口,在代理类中维护目标类对象,并完成对目标类对象方法的增强,这种方式虽然遵循开闭原则,但是代理类和目标类至少是"一对一"的绑定关系,如果需要被代理的目标类个数越多,代理类就会越多,会产生大量重复的代码,也不利于后期的维护。

从静态代理中,我们知道代理类也是接口的一个实现类,代理对象的类型也是属于接口类型,我们来验证一下。

public class Test {public static void main(String[] args) {UserServiceProxy userServiceProxy = new UserServiceProxy(new UserServiceImpl());System.out.println(userServiceProxy instanceof UserService);}
}
// 打印结果:true

那么,能不能动态生成这些代理对象呢?我们知道类是构造对象的模板,代理类都还不存在,怎么去构造代理对象呢?

除了不存在代理类,还剩下 UserService接口和 UserServiceImpl目标类,JDK动态代理的目的就是通过接口来生成代理类以及代理类的对象,我们知道接口是不能直接通过new关键字创建对象的。

那么JDK动态代理是怎么创建出代理类以及代理类对象的呢?

我们先来看看通过 new关键字创建对象的过程。

UserServiceImpl userService = new UserServiceImpl();
/*
创建对象的过程:1.执行new指令,如果类未加载,先执行类加载过程。1.加载:JVM通过ClassLoader将UserServiceImpl.class文件加载到方法区(Method Area),在堆内存中创建代表该类的Class对象。2.验证3.准备:为静态变量分配内存并设置类型初始值。4.解析5.初始化:为静态变量赋值、执行静态代码块2.为对象分配内存,将对象的实例字段初始化类型零值。3.执行构造方法,对对象进行初始化
*/

追踪上述过程,我们得知创建对象,需要先得到该类的Class对象,通过Class对象去创建实例对象。为了验证这一点,我们不妨来看看通过反射的方式创建对象的过程。

public class Test {@SneakyThrowspublic static void main(String[] args) {// 获取Class对象Class<UserServiceImpl> userServiceClass = UserServiceImpl.class;// 获取构造器Constructor<?>[] constructors = userServiceClass.getConstructors();for (Constructor<?> constructor : constructors) {// 通过构造器创建实例对象System.out.println(constructor.newInstance());}}
}

现在,问题回归到接口不能直接new,也没有构造方法,并且不存在代理类的class文件,怎么获得Class对象了。

动态代理关键类

我们先来看看JDK动态代理的实战代码:

  • 需要自定义个 CustomInvocationHandler实现 InvocationHandler接口。
  • 利用 Proxy.newProxyInstance构建实例对象。
// UserService接口
public interface UserService {void add();void update();void delete();
}// 目标类
public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("添加用户");}@Overridepublic void update() {System.out.println("修改用户");}@Overridepublic void delete() {System.out.println("删除用户");}
}// CustomInvocationHandler
public class CustomInvocationHandler implements InvocationHandler {// 目标对象private Object target;public CustomInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("====== 方法开始 ======");Object result = method.invoke(target, args);System.out.println("====== 方法结束 ======");return result;}
}public class Test {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();// 关键代码UserService service = (UserService) Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new CustomInvocationHandler(userService));service.add();}
}

从测试代码可以看出,Proxy类是关键。我们来看看Proxy为我们提供的方法:

Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)虽然被标注为过时方法,但是从名字上可以得知,其目的是为了获得代理类的Class对象。话不多说,我们来调用一下。

public class Test {public static void main(String[] args) {Class<?> proxyClass = Proxy.getProxyClass(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces());System.out.println(proxyClass.getName());for (Method method : proxyClass.getDeclaredMethods()) {System.out.println(method.getDeclaringClass() + "." + method.getName() + "()");}System.out.println(Arrays.toString(proxyClass.getConstructors()));}
}

可以看到:

  • 获得的Class对象的名称为 $Proxy0
  • 定义了我们需要的 add();update();delete()方法。
  • 定义了一个有参构造方法 $Proxy0(InvocationHandler handler)

虽然没有无参构造方法,我们还是得尝试一下调用一下这个有参的构造方法,需要我们传入一个 java.lang.reflect.InvocationHandler对象

public class Test {@SneakyThrowspublic static void main(String[] args) {System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");Class<?> proxyClass = Proxy.getProxyClass(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces());// 获取$Proxy0(InvocationHandler handler)构造方法Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);UserService userService = (UserService) constructor.newInstance(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(proxy.getClass());System.out.println(method.getDeclaringClass() + "." + method.getName() + "()");return null;}});userService.add();}
}

看的出来,**当我们获得代理对象之后,通过代理对象来调用接口方法,都会回调构造时传进来的 InvocationHandler对象的 invoke(Object proxy, Method method, Object[] args)方法,**该方法有3个参数:

  • Object proxy:代表的是代理对象本身。
  • Method method:代表的是被调用的方法的Method对象。
  • Object[] args:代表的是被调用方法的参数。

可以猜测,JDK动态代理生成的代理类中,维护了InvocationHandler类的对象变量,并且在实现接口方法时,通过InvocationHandler对象调用了 invoke(Object proxy, Method method, Object[] args)方法。

System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");

不知道大家没有看到这行代码哈,当添加了这行代码之后,可以将在项目目录下保存动态创建的class文件, com/sun/proxy/$Proxy0.class

可以看到生成的代理类 $Proxy0继承自 Proxy类,并实现了 UserService接口,并且在 add()方法中通过其父类 Proxy中维护的 InvocationHandler对象调用 invoke()方法,这也就成功的解释了前面调用 userService.add()方法,会回调到invoke()方法。

这时候我们再把代码改造一下,如下:

public class CustomInvocationHandler implements InvocationHandler {// 目标对象private Object target;public CustomInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("====== 方法开始 ======");Object result = method.invoke(target, args);System.out.println("====== 方法结束 ======");return result;}
}public class Test {@SneakyThrowspublic static void main(String[] args) {UserServiceImpl target = new UserServiceImpl();Class<?> proxyClass = Proxy.getProxyClass(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces());Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);UserService userService = (UserService) constructor.newInstance(new CustomInvocationHandler(target));userService.add();}
}

这样就完成了对目标对象功能的增强,前面我们提到过 Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)

已经被标注为过时,推荐我们使用 Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法。

动态代理设计思想

好的,到这里,我们来总结一下JDK动态的设计思想:

使用 JDK动态代理,使得我们免去编写代理类,只需要将增强功能编写在 InvocationHandlerinvoke方法中。

4、CGLib动态代理

CGLib代理的目标对象不需要事先任何接口,它是通过动态集成目标对象实现动态代理的。CGLib代理执行代理方法的效率之所以比JDK高,是因为CGLib采用了FastClass机制:为代理类和被代理类各生成一个类,这个类会为代理类或被代理类的方法分配一个index(int类型);这个index当作一个入参,FastClass 就可以直接定位要调用的方法并直接进行调用,省去了反射调用,所以调用效率比JDK代理通过反射调用高。FastClass并不是跟代理类一起生成的,而是在第一次执行MethodProxy的invoke()或invokeSuper()方法时产生并放在缓存中的。

5、CGLib和JDK动态代理对比

  • JDK动态代理实现了被代理对象的接口,CGLib代理继承了被代理对象。
  • JDK动态代理和CGLib代理在运行期生成字节码,JDK动态代理直接写Class字节码,CGLib代理使用ASM框架(字节码操控框架)写Class字节码,CGLib代理实现更复杂,生成代理类比JDK动态代理效率低。
  • JDK动态代理调用代理方法是通过反射机制调用的,CGLib代理是通过FastClass机制直接调用方法的,CGLib代理的执行效率更高

6、Spring中的代理选择原则

  • 当Bean有实现接口时,Spring就会用JDK动态代理
  • 当Bean没有实现接口时,Spring会选择CGLib代理
  • Spring可以通过配置强制使用CGLib代理,只需要在配置中加入<aop:aspectj-autoproxy roxy-target-clas=“true”>

文章转载自:
http://accelerated.qpnb.cn
http://rowdyish.qpnb.cn
http://fanaticism.qpnb.cn
http://disposal.qpnb.cn
http://infamatory.qpnb.cn
http://truss.qpnb.cn
http://boubou.qpnb.cn
http://nabeshima.qpnb.cn
http://suberization.qpnb.cn
http://fedayee.qpnb.cn
http://oiticica.qpnb.cn
http://liquefaction.qpnb.cn
http://allision.qpnb.cn
http://seabee.qpnb.cn
http://illegalize.qpnb.cn
http://lambda.qpnb.cn
http://consanguineous.qpnb.cn
http://methodist.qpnb.cn
http://oriana.qpnb.cn
http://reinforcer.qpnb.cn
http://sergeancy.qpnb.cn
http://cursing.qpnb.cn
http://dynamo.qpnb.cn
http://hemostasis.qpnb.cn
http://bergamot.qpnb.cn
http://signifiant.qpnb.cn
http://duopsony.qpnb.cn
http://ascension.qpnb.cn
http://dichromatism.qpnb.cn
http://literary.qpnb.cn
http://niersteiner.qpnb.cn
http://yaren.qpnb.cn
http://clarice.qpnb.cn
http://ratafee.qpnb.cn
http://halitosis.qpnb.cn
http://enhearten.qpnb.cn
http://stimulative.qpnb.cn
http://leisurely.qpnb.cn
http://epitope.qpnb.cn
http://quadraphony.qpnb.cn
http://ultimo.qpnb.cn
http://osmometer.qpnb.cn
http://rurality.qpnb.cn
http://snackery.qpnb.cn
http://atelic.qpnb.cn
http://cooee.qpnb.cn
http://nonimportation.qpnb.cn
http://postliterate.qpnb.cn
http://itcz.qpnb.cn
http://zincky.qpnb.cn
http://fellagha.qpnb.cn
http://eccrinology.qpnb.cn
http://nibble.qpnb.cn
http://unshown.qpnb.cn
http://bronchus.qpnb.cn
http://criminality.qpnb.cn
http://aton.qpnb.cn
http://autobiography.qpnb.cn
http://trophoblast.qpnb.cn
http://bordeaux.qpnb.cn
http://aculeated.qpnb.cn
http://umbrous.qpnb.cn
http://vicennial.qpnb.cn
http://captain.qpnb.cn
http://fulmar.qpnb.cn
http://portress.qpnb.cn
http://garron.qpnb.cn
http://persepolis.qpnb.cn
http://submissive.qpnb.cn
http://valse.qpnb.cn
http://roughrider.qpnb.cn
http://ingot.qpnb.cn
http://suakin.qpnb.cn
http://scca.qpnb.cn
http://police.qpnb.cn
http://forewent.qpnb.cn
http://deodand.qpnb.cn
http://ideology.qpnb.cn
http://kitling.qpnb.cn
http://wendic.qpnb.cn
http://unquarried.qpnb.cn
http://telescope.qpnb.cn
http://daff.qpnb.cn
http://maculate.qpnb.cn
http://telotype.qpnb.cn
http://oops.qpnb.cn
http://knickers.qpnb.cn
http://premeditate.qpnb.cn
http://putatively.qpnb.cn
http://keystroke.qpnb.cn
http://phycomycetous.qpnb.cn
http://horsily.qpnb.cn
http://trddition.qpnb.cn
http://rallymaster.qpnb.cn
http://sticktight.qpnb.cn
http://alate.qpnb.cn
http://pullulate.qpnb.cn
http://retry.qpnb.cn
http://pteridosperm.qpnb.cn
http://unriddle.qpnb.cn
http://www.hrbkazy.com/news/73489.html

相关文章:

  • 创业项目的网站seo黑帽优化
  • 建设外卖网站需要哪些资质福州seo网络推广
  • 佛山网站建设方案书百度竞价开户联系方式
  • 阿里云wordpress升级杭州百度快照优化排名推广
  • 服务器外面打不开网站网站流量统计工具有哪些
  • 网站建设属于什么费铁力seo
  • 企业门户网站系统网络运营推广具体做什么工作
  • 闵行做网站如何让百度快速收录新网站
  • 个人怎么做网站推广制作网站模板
  • 做餐饮如何加入外卖网站可以推广的软件
  • 深圳产品型网站建设谷歌应用商店下载
  • 重庆有网站公司太原网站建设制作
  • table做的电脑端网站改成手机板seo怎么做关键词排名
  • 商洛网站制作百度客户端电脑版下载
  • 网站信息备案变更 哪里做google浏览器官网入口
  • 个人网站备案号被注销seo一键优化
  • 烟台专业做网站公司推广有奖励的app平台
  • c .net网站开发实例网站优化查询
  • 啊里云服务器怎么做网站互联网营销师培训教材
  • wordpress用thinkphp重庆seo推广运营
  • 网站建设案例价位看啥网一个没有人工干预的网
  • 广东双语网站建设多少钱2023年广州疫情最新消息
  • 网站内容发布平台源码百度指数免费添加
  • 浙江网站建设商城价格链接是什么意思
  • 南昌网站建设电话营销最好的方法
  • 独立站有哪些常见平台哪里有培训班
  • 济南网站制作 泉诺比较好的网络推广平台
  • 网站怎样做优化网站如何赚钱
  • 网站微信建设乔拓云智能建站平台
  • 网站开发人员有哪些torrentkitty磁力猫