Core API之Method结构

本文详细介绍了Java字节码中Method的结构,包括Execution model和Bytecode instructions。讲解了opcode、arguments及其作用,分类讨论了各种字节码指令,如stack操作、Constant、Arithmetic and logic运算、Casts、Object、Fields、Method、Arrays、Jumps以及Return指令,帮助读者深入理解Java方法执行的底层机制。

    在编译后class内部,method的代码以字节码指令序列的方式存储。为了生成和转换class,最基本的是知道这些指令、了解它们如何工作。

Execution model

    Java代码在线程内被执行。每个线程有自己的执行栈,它由frame组成。每个frame代表了一个方法调用:每个时间一个方法被调用,新frame被压入当前线程的执行栈,当方法正常返回或有异常,这个frame被弹出栈且继续执行。
   每个frame有两部分:本地变量和操作栈 。本地变量可以通过index随机访问,操作栈被字节码指令操作。即意味着此栈中的值只能以LIFO顺序访问。
本地变量和操作栈的大小依赖于method code。它在编译时间就被计算且随字节码指令一起存春在class中。所有frame的大小都一样,但不同方法对应的frame的本地变量和操作栈的大小不一样。
   上图展示了一个执行栈有三个frame,第一个frame有3个本地变量,它的操作栈大小为4,有量个值。当一个frame被创建后,它被初始化为空操作栈,它的本地变量初始化为目标对象this,和方法参数。例如调用a.equals(b),创建一个空操作栈,前两个本地变量初始为a和b,其他的本地变量没有初始化。
    在本地变量和操作栈中的slot可以容纳任何java值,除了long和double值之外。这些值需要两个slot。例如调用Math.max(1L,2L),创建一个frame,1L占用第一、第二个slot,2L占用第三、第四个slot。

Bytecode instructions

    一个字节码指定由操作码和固定数值的参数组成。

    1) opcode:无符号byte。字节码名称,通过记忆性字符标记。例如opcode值0用NOP来标记,表示指定不做任何事情。 

    2)arguments:定义指定精确行为的静态值。它们在opcode之后给出。例如GOTO label指令,它的opcode值是167,接受一个参数lable。lable表示下一个指令要执行的地方。指令参数和指定操作数不能混淆。参数值是静态的,存储在编译好的代码中,而操作值来自于操作栈,它们仅在运行时才直到。

    字节码指令可以被分为两类:一小类,从本地变量到操作栈的值传输。另外一类指令仅在操作栈上执行,它们从栈中弹出值,计算结果,压回栈。ILOAD,LLOAD,FLOAD,ALOAD指令读取本地变量,将值压入操作栈。它们接受本地变量的Index作为参数。ILOAD用来加载boolean,byte、char、short、int本地变量。LLOAD,FLOAD和DLOAD各自用来加载long、float、double值(LLOAD和DLOAD实际上加载i和i+1两个slot)。ALOAD用来加载非基本类型值,如object数组引用。类似ISTORE,LSTORE,FSTORE,DSTORE和ASTORE指令从操作栈弹出值并存储到本地变量index中。

    xload和xstore指令都是有类型的,确保没有非法的转换。在方法执行过程中存储在本地变量中的值能发生变化。所有其他字节码指令仅在操作栈上工作。它们可以被归为以下几类:
    stack:这些指令用来操作操作栈上的值。POP,栈顶元素出栈。DUP,压入栈顶元素的拷贝。SWAP,出栈2元素,且以相反的顺序入栈。
    Constant:将常量值压入到栈顶。ACONST_NULL压入null,ICONST_0压入0,FCONST_0压入0f,DCONST_0压入0d。BIPUSH b将字节值b压入栈。SIPUSH s 将short类型 s压入栈。LDC压入二进制int、float、long、double,string或class常量。
    Arithmetic and logic(算术和逻辑运算):这些指令将数值从操作栈出栈,接着运算并见结果压入栈。它们不包含任何参数。xADD,xSUB,xMUL,xDIV和xREM对应响应的+,-,*,/,%运算,这里的x要么是I,L,F,D。类似,这里有其他指令对应<<,>>,>>>,|,&和^。
    Casts:该指令从栈弹出值,转换为另外一个类型,并将结果压入栈。它对应Java中的转换表达式。I2F,F2D,L2D。CHECKCAST t转换一个引用到另一个类型t。
    Object:该指令用来创建对象、锁定它们、测试它们的类型。例如 NEW type指令将一个新的对象压入栈
    Fields:该指令读取或写filed的值。GETFIELD owner name desc 指令从栈中弹出对象引用,并压入name field的值。PUTFIELD owner name desc弹出一个值和对象引用,储存值到name域上。上述例子中,object必须是 owner类型,它的filed必须是desc类型。GETSTATIC和PUTSTATIC针对静态域。
    Method:这些指令调用方法或构造器。当方法有参数时,它们pop多个value,另外,一个值为target对象,且将方法调用的返回值压入栈。INVOKEVIRTUAL owner name desc调用方法owner类中方法名为name的方法,其中整个方法描述为desc。INVOKESTATIC用来调用静态方法。INVOKESPECIAL调用私有方法和是有构造器。INVOKEINTERFACE调用接口中定义的方法。
    Arrays:该指令用来读取和写如数组中的值。xALOAD指令pop一个index和一个数组并且将index处的array值压入栈。xASTORE指令pop一个值、index和value和数组,并且在数组中index位置存储这个值。x可以是I,L,F,D,A也可以是B,C和S。
    Jumps:如果某条件为真,该指令跳转到二进制指令。它们用于编译if,for,do,while,break和continue指令。例如,IFEQ label pop一个int,如果value为0,跳转到指令lable。还有许多其他jump指令,如IFNE,IFGE。TABLESWITCH和lookupswitch对应Java的switch指令。
    Return:xReturn和Return指令用来终止方法执行且返回结果到调用者。Return对应void,xReturn对应其他方法返回类型。

Examples

package pkg;
public class Bean {
    private int f;
    public int getF() {
        return this.f;
    }
    public void setF(int f) {
        this.f = f;
    }
}
get方法的字节码是:

ALOAD 0
GETFIELD pkg/Bean f I
IRETURN
    第一个指令读取index为0本地变量,该值在get方法调用创建frame时初始化给this对象,且将这个值压入操作栈。第二个指令从栈弹出值(例如this),且压入该对象的f 数据域最后一个指令弹出这个值返回调用者。
set方法的字节码:
ALOAD 0
ILOAD 1
PUTFIELD pkg/Bean f I
RETURN
    第一个指令将第一个本地变量this压入操作栈。第二指令将index=1本地变量压入栈,该变量在set方法的frame被创建时,使用参数f的值初始化。第三个指令弹出这些值,且在this对象的f field上存储int值。最后一条指令,销毁当前执行frame,且返回给调用者。
bean class幽默人的public构造函数:
Bean(){
    super();
}
构造函数字节码:

ALOAD 0
INVOKESPECIAL java/lang/Object <init> ()V
RETURN
    第一条指令将index=0本地变量this压入操作栈。第二条指令弹出值,调用Object的<init>方法。第三条指令返回调用者
更复杂的set方法:
public void checkAndSetF(int f) {
    if (f >= 0) {
        this.f = f;
    } else {
        throw new IllegalArgumentException();
    }
}
对应的字节码:
ILOAD 1
IFLT label
ALOAD 0
ILOAD 1
PUTFIELD pkg/Bean f I
GOTO end
label:
NEW java/lang/IllegalArgumentException
DUP
INVOKESPECIAL java/lang/IllegalArgumentException <init> ()V
ATHROW
end:
RETURN
    第一条指令将index=1的本地变量入栈,初始化到f。IFLT指令将值从栈中弹出,并且将它与0比较,如果less than(LT)0,跳转到Lable label。否则do nothing且执行下一条指令。紧接着三条指令与setF方法中的指令相同。GOTO指令无条件跳转到END lable。lable与end之间的指令创建异常并抛出异常。NEW指令创建异常对象并压入操作栈。DUP指令复制在栈顶的值。INVOKESPECIAL指令弹出两分拷贝中的一个,并它的异常构造函数。最后athrow指令弹出剩下的拷贝,抛出异常。


<think>我们讨论的是ASP.NET Core Web API项目的典型结构以及一些关键部分的语法。由于项目结构是标准化的,我将按照常见的项目组织方式逐一解释,并给出关键代码示例。 典型的ASP.NET Core Web API项目结构如下: 1. **Program.cs**:应用程序的入口点,负责配置主机和启动。 2. **Startup.cs**(在较新版本中,启动配置已合并到Program.cs,但为兼容性,我们也会提到): 配置服务和HTTP请求管道。 3. **appsettings.json**:配置文件,用于存储应用设置(如数据库连接字符串)。 4. **Controllers**:包含处理HTTP请求的控制器类。 5. **Models**:包含数据模型(实体)和DTO(数据传输对象)。 6. **Services**(可选):包含业务逻辑服务类。 7. **Data**(可选):包含数据库上下文和数据访问层(如使用Entity Framework Core)。 8. **Middleware**(可选):自定义中间件。 9. **Properties/launchSettings.json**:启动配置文件(如IIS设置、环境变量等)。 ### 详细说明及代码示例 #### 1. Program.cs 在.NET 6及更高版本中,使用顶级语句,因此Program.cs非常简洁。它创建了一个WebApplicationBuilder,配置服务,然后构建应用并配置中间件。 ```csharp var builder = WebApplication.CreateBuilder(args); // 添加服务到容器 builder.Services.AddControllers(); // 添加控制器服务 // 添加Swagger生成器(可选) builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 配置HTTP请求管道 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); // 映射控制器路由 app.Run(); ``` #### 2. Startup.cs(旧版模式,在.NET 5及以前) 在旧版模板中,Startup.cs有两个方法:`ConfigureServices`和`Configure`。在.NET 6+中,这些配置可以放在Program.cs中,但为了兼容性,我们也可以使用Startup类。 ```csharp public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); // 其他服务注册... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } ``` #### 3. appsettings.json 配置文件示例: ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;" } } ``` #### 4. Controllers 控制器类负责处理HTTP请求。每个公共方法通常是一个动作(Action),可通过路由访问。 ```csharp [ApiController] [Route("api/[controller]")] public class WeatherForecastController : ControllerBase { [HttpGet] public IEnumerable<WeatherForecast> Get() { // 返回数据 } [HttpGet("{id}")] public ActionResult<WeatherForecast> GetById(int id) { // 根据id获取数据 } [HttpPost] public IActionResult Create(WeatherForecast forecast) { // 创建新资源 return CreatedAtAction(nameof(GetById), new { id = forecast.Id }, forecast); } } ``` #### 5. Models 模型类代表数据结构。 ```csharp public class WeatherForecast { public int Id { get; set; } public DateTime Date { get; set; } public int TemperatureC { get; set; } public string Summary { get; set; } } ``` #### 6. Services 服务类包含业务逻辑,通过依赖注入注入到控制器。 ```csharp public interface IWeatherService { IEnumerable<WeatherForecast> GetForecasts(); } public class WeatherService : IWeatherService { public IEnumerable<WeatherForecast> Getcasts() { // 业务逻辑 } } ``` 在Program.cs中注册服务: ```csharp builder.Services.AddScoped<IWeatherService, WeatherService>(); ``` 在控制器中使用: ```csharp [ApiController] [Route("api/[controller]")] public class WeatherForecastController : ControllerBase { private readonly IWeatherService _weatherService; public WeatherForecastController(IWeatherService weatherService) { _weatherService = weatherService; } [HttpGet] public IEnumerable<WeatherForecast> Get() { return _weatherService.Getcasts(); } } ``` #### 7. Data(使用Entity Framework Core) 定义DbContext: ```csharp public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<WeatherForecast> WeatherForecasts { get; set; } } ``` 在Program.cs中注册: ```csharp builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); ``` #### 8. Middleware 自定义中间件示例: ```csharp public class RequestLoggingMiddleware { private readonly RequestDelegate _next; public RequestLoggingMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { Console.WriteLine($"Request path: {context.Request.Path}"); await _next(context); Console.WriteLine($"Response status: {context.Response.StatusCode}"); } } ``` 在Program.cs中使用: ```csharp app.UseMiddleware<RequestLoggingMiddleware>(); ``` ### 总结 ASP.NET Core Web API项目结构清晰,各部分职责明确: - **Program.cs**:配置主机和中间件管道。 - **配置文件**:appsettings.json存储配置。 - **控制器**:处理HTTP请求。 - **模型**:定义数据结构。 - **服务**:实现业务逻辑。 - **数据访问**:通过EF Core与数据库交互。 - **中间件**:处理请求和响应的管道组件。 §§相关问题§§: 1. ASP.NET Core中的依赖注入是如何工作的? 2. 如何配置和使用身份验证(如JWT)在Web API中? 3. 在ASP.NET Core中,中间件的执行顺序是怎样的? 4. 如何使用Entity Framework Core进行数据库迁移(Migrations)?</think>### ASP.NET Core Web API 项目结构详解 ASP.NET Core Web API 项目采用清晰的层次化结构,以下是典型项目结构及各部分详细说明: #### 1. **项目根目录** ```bash MyWebApi/ ├── Properties/ ├── Controllers/ ├── Models/ ├── Services/ ├── Data/ ├── appsettings.json ├── Program.cs └── Startup.cs (旧版模板) ``` #### 2. **核心文件详解** ##### 2.1 Program.cs - 应用入口点 ```csharp var builder = WebApplication.CreateBuilder(args); // 添加服务到容器 builder.Services.AddControllers(); // 添加控制器支持 builder.Services.AddEndpointsApiExplorer(); // API文档支持 builder.Services.AddSwaggerGen(); // Swagger文档生成 var app = builder.Build(); // 配置HTTP请求管道 if (app.Environment.IsDevelopment()) { app.UseSwagger(); // 开发环境启用Swagger app.UseSwaggerUI(); // 提供Swagger UI界面 } app.UseHttpsRedirection(); // HTTPS重定向 app.UseAuthorization(); // 授权中间件 app.MapControllers(); // 映射控制器路由 app.Run(); // 启动应用 ``` **功能说明**: - `.AddControllers()`:注册API控制器 - `UseSwagger()`:启用OpenAPI文档 - `MapControllers()`:自动映射控制器路由 ##### 2.2 appsettings.json - 配置文件 ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "Server=.;Database=MyDB;Trusted_Connection=True;" }, "Jwt": { "Key": "your_super_secret_key", "Issuer": "your_issuer" } } ``` #### 3. **核心目录结构** ##### 3.1 Controllers/ - API端点 ```csharp [ApiController] [Route("api/[controller]")] public class ProductsController : ControllerBase { private readonly IProductService _productService; // 依赖注入 public ProductsController(IProductService productService) { _productService = productService; } [HttpGet] public async Task<ActionResult<IEnumerable<Product>>> GetProducts() { var products = await _productService.GetAllProducts(); return Ok(products); // 200 OK响应 } [HttpGet("{id}")] public async Task<ActionResult<Product>> GetProduct(int id) { var product = await _productService.GetProductById(id); return product != null ? Ok(product) : NotFound(); // 404处理 } [HttpPost] public async Task<ActionResult<Product>> CreateProduct(ProductDto productDto) { var createdProduct = await _productService.CreateProduct(productDto); return CreatedAtAction(nameof(GetProduct), new { id = createdProduct.Id }, createdProduct); // 201 Created响应 } } ``` **路由特性**: - `[Route("api/[controller]")]`:自动生成路由(如 `/api/products`) - `[HttpGet]`/`[HttpPost]`:定义HTTP方法 - `{id}`:路由参数绑定 ##### 3.2 Models/ - 数据模型 ```csharp public class Product { public int Id { get; set; } [Required] [StringLength(100)] public string Name { get; set; } [Range(0.01, 10000)] public decimal Price { get; set; } [ForeignKey("Category")] public int CategoryId { get; set; } public Category Category { get; set; } } // DTO (数据传输对象) public class ProductDto { [Required] public string Name { get; set; } public decimal Price { get; set; } } ``` **数据注解**: - `[Required]`:必填字段验证 - `[StringLength]`:字符串长度限制 - `[Range]`:数值范围验证 ##### 3.3 Services/ - 业务逻辑 ```csharp public interface IProductService { Task<IEnumerable<Product>> GetAllProducts(); Task<Product> GetProductById(int id); Task<Product> CreateProduct(ProductDto productDto); } public class ProductService : IProductService { private readonly AppDbContext _context; public ProductService(AppDbContext context) { _context = context; } public async Task<IEnumerable<Product>> GetAllProducts() { return await _context.Products.Include(p => p.Category).ToListAsync(); } public async Task<Product> GetProductById(int id) { return await _context.Products.FindAsync(id); } public async Task<Product> CreateProduct(ProductDto productDto) { var product = new Product { Name = productDto.Name, Price = productDto.Price }; _context.Products.Add(product); await _context.SaveChangesAsync(); return product; } } ``` **依赖注入注册** (在Program.cs中): ```csharp builder.Services.AddScoped<IProductService, ProductService>(); ``` ##### 3.4 Data/ - 数据访问层 ```csharp public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Product> Products { get; set; } public DbSet<Category> Categories { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置关系 modelBuilder.Entity<Product>() .HasOne(p => p.Category) .WithMany(c => c.Products) .HasForeignKey(p => p.CategoryId); } } ``` **数据库配置** (Program.cs): ```csharp builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); ``` #### 4. **高级特性示例** ##### JWT认证 ```csharp // Program.cs中添加 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }); ``` ##### 自定义中间件 ```csharp public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public RequestLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) { _next = next; _logger = loggerFactory.CreateLogger<RequestLoggingMiddleware>(); } public async Task Invoke(HttpContext context) { _logger.LogInformation($"Request: {context.Request.Method} {context.Request.Path}"); await _next(context); _logger.LogInformation($"Response: {context.Response.StatusCode}"); } } // 注册中间件 (Program.cs) app.UseMiddleware<RequestLoggingMiddleware>(); ``` ### 项目关键点总结 1. **依赖注入**:内置IoC容器管理服务生命周期 2. **中间件管道**:请求处理流程的可扩展架构 3. **配置系统**:分层配置(环境变量 > appsettings.{env}.json > appsettings.json) 4. **环境管理**:通过`IHostEnvironment`区分开发/生产环境 5. **OpenAPI支持**:自动生成API文档 6. **异步编程**:全面支持async/await模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值