简述一下maven在java项目开发管理中的作用以及maven javaweb项目的结构特点是什么?
在这篇文章中,我们将深入探讨Maven的核心功能和基本使用方法,揭示其在项目管理和构建过程中的强大优势。
同时,我们还将介绍动态代理和静态代理的概念。
特别是通过Proxy和InvocationHandler,我们将具体演示动态代理的实现方式,帮助你理解这一技术如何提升代码的灵活性和可维护性。
这篇文章将为你提供实用的知识与技巧,无论你是Maven的新手还是希望进一步掌握代理模式的开发者,都能在这里找到有价值的内容。
Maven
Maven似乎专门为Java项目打造的管理和构建工具。
Maven主要功能:
- 提供了一套标准化的项目结构
- 提供了一套标准化的构建流程
- 提供了一套依赖管理机制
- Maven使用groupId、artifactId、version唯一定位一个依赖。
- Maven中声明一个依赖项可以自动下载和导入classpath。
Maven作用:
- 解决了依赖管理,当我们写项目时,需要一个jar包,但是这个jar包还依赖其他的jar包。通过Maven我们就可以不用考虑这个问题,Maven会自动导入我们指定的jar包和其相依赖的jar包。
Maven定义了几种依赖关系
- compile(默认),编译时需要用到该jar包
- test,编译Test时需要用到该jar包
- runtime,编译时不需要,但运行时需要用到
- provided,编译时需要用到,但运行时由JDK或某个服务器提供
唯一ID
- 对于某个依赖,Maven只需要3个变量即可唯一确定某个jar包:
- groupId:属于组织的名称,类似Java的包名;
- artifactId:该jar包自身的名称,类似Java的类名;
- version:该jar包的版本。
- 通过上述3个变量,即可唯一确定某个jar包。Maven通过对jar包进行PGP签名确保任何一个jar包一经发布就无法修改。修改已发布jar包的唯一方法是发布一个新版本。
- 因此,某个jar包一旦被Maven下载过,即可永久地安全缓存在本地。
代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,它通过提供一个代理对象来控制对另一个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在访问目标对象前后添加额外的逻辑。
代理就是为其他对象提供一种代理,以控制对这个对象的访问。
代理模式的分类
1.静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般做一些附属操作
- 客户:访问代理对象的人
代码步骤:
- 接口
- 真实角色
- 代理角色
- 客户端访问代理角色
静态代理好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
- 公共业务就交给代理角色!实现类业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低。
注意:
- 改动原有的业务代码,在公司是大忌!!
2.动态代理(这个代理不用自己创建,不用像静态代理那样)
角色:
- 动态代理和静态代理角色一样
动态代理的代理类是动态生成的,不是我们直接写好的。
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:JDK的动态代理【我们在这里使用】
- 基于类:cglib
- java字节码实现:javasist
需要了解两个类:Proxy(代理)、InvocationHandler(调用处理程序)
InvocationHandler,接口,java.lang.reflect
- InvocationHandler是由代理实例的调用处理程序实现的接口。
- 每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
- 该接口的方法 invoke(Object proxy,方法 method,Object[] args),处理代理实例上的方法调用并返回结果
Proxy,实现类,java.lang.reflect
- Proxy提供了静态方法来创建动态代理类和实例,它也是由这些方法创建的所有动态代理类的超类。
动态代理的好处:
- 除了静态代理的好处;
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务;
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可。
咳咳,这是一个万能公式!!!
//等会我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setRent(Object target){
this.target=target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
// 处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现的!
// System.out.println("这里被实现了");
Object result = method.invoke(target, args);
return result;
}
}
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象!
pih.setRent(host);
Rent proxy = (Rent)pih.getProxy();
System.out.println(proxy.rent());
}
}
为什么要使用代理?
首先,为什么要使用代理?在一个成熟的系统中,如果我们想在不改变源码的基础上增加一些功能,就需要再套一层代理。在这个代理中实现我们要增加的功能。这里可以使用静态代理来实现。但是静态代理有一些问题,比如会增加代码量,影响效率。这时可以使用动态代理。
动态代理使用 Proxy 和 InvocationHandler 这两个类,可以对一个类,甚至多个类(只要它们实现了同一个接口)进行代理。通过这两个类,可以实现动态加载代理类,而不需要创建静态代理类。当动态代理对象生成时,通过某种机制触发 InvocationHandler 中的 invoke 方法,从而调用接口实现类对象的方法。同时,可以在 invoke 方法中实现其他额外的代码,这正是我们需要的。
这样的动态代理,既可以不改变原有的代码,又可以通过较少的代码量实现新增加的功能,漂亮!
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:【知乎】。