### Netty Server Setup with Outbound Channel Handlers Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Illustrates a modified Netty `ServerBootstrap` configuration to include `OutBoundHandlerA`, `OutBoundHandlerB`, and `OutBoundHandlerC` in the `ChannelPipeline`. This setup demonstrates how outbound handlers are added and positioned for processing outgoing data. ```Java public final class Server { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, true) .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue") .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new OutBoundHandlerA()); ch.pipeline().addLast(new OutBoundHandlerB()); ch.pipeline().addLast(new OutBoundHandlerC()); } }); ChannelFuture f = b.bind(8888).sync(); ``` -------------------------------- ### Example Netty Inbound Handler: InBoundHandlerA Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Provides an example implementation of a Netty ChannelInboundHandlerAdapter, demonstrating how to process inbound messages. It shows how to print the received message and then propagate it further down the pipeline using ctx.fireChannelRead. ```java public class InBoundHandlerA extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("InBoundHandlerA: " + msg); ctx.fireChannelRead(msg); } } ``` -------------------------------- ### Netty Server Bootstrap Configuration and Binding Example Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-Netty服务端启动分析.md This Java code demonstrates the basic setup for a Netty server using `ServerBootstrap`. It configures `EventLoopGroup`s for boss and worker threads, specifies the channel type (`NioServerSocketChannel`), sets channel options like `TCP_NODELAY`, and initializes the `ChannelPipeline` with custom handlers (`ServerHandler`, `AuthHandler`). The server then binds to port 8888 and waits for the channel to close. ```java public final class Server { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, true) .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue") .handler(new ServerHandler()) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new AuthHandler()); //.. } }); ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ``` -------------------------------- ### Netty HttpHelloWorldServerInitializer Example Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(上).md Illustrates a concrete implementation of `ChannelInitializer`, specifically `HttpHelloWorldServerInitializer`, which extends `ChannelInitializer`. This example demonstrates how to override the `initChannel` method to add various `ChannelHandler`s (like `SslContext`, `HttpServerCodec`, `HttpServerExpectContinueHandler`, and `HttpHelloWorldServerHandler`) to the `ChannelPipeline` for an HTTP server. ```Java public class HttpHelloWorldServerInitializer extends ChannelInitializer { private final SslContext sslCtx; public HttpHelloWorldServerInitializer(SslContext sslCtx) { this.sslCtx = sslCtx; } @Override public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc())); } p.addLast(new HttpServerCodec()); p.addLast(new HttpServerExpectContinueHandler()); p.addLast(new HttpHelloWorldServerHandler()); } } ``` -------------------------------- ### Java String Interning Method Usage Examples Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/JDK/深入学习String源码与底层(一).md This Java code provides examples of using the `String.intern()` method in conjunction with string concatenation and literal assignments. It includes comparisons to illustrate the behavior of `intern()` and how it interacts with the string constant pool and heap-allocated objects. ```Java String a1 = new String("AA") + new String("BB"); System.out.println("a1 == a1.intern() " + (a1 == a1.intern())); String test = "ABABCDCD"; String a2 = new String("ABAB") + new String("CDCD"); String a3 = "ABAB" + "CDCD"; System.out.println("a2 == a2.intern() " + (a2 == a2.intern())); System.out.println("a2 == a3 " + (a2 == a3)); System.out.println("a3 == a2.intern() " + (a3 == a2.intern())); ``` -------------------------------- ### JVM Local Variable Table Example Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/JDK/深入学习String源码与底层(一).md This snippet displays the structure of the LocalVariableTable, detailing the start, length, slot, name, and signature for local variables within a JVM method, including String array arguments and String objects. ```JVM Bytecode LocalVariableTable: Start Length Slot Name Signature 0 17 0 args [Ljava/lang/String; 3 14 1 name Ljava/lang/String; 6 11 2 name2 Ljava/lang/String; 16 1 3 name3 Ljava/lang/String; ``` -------------------------------- ### Spring XmlBeanDefinitionReader Initialization and Bean Loading Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/深入Spring源码系列(二)——深入Spring容器,通过源码阅读和时序图来彻底弄懂Spring容器(下).md This Java code snippet illustrates the setup and use of XmlBeanDefinitionReader within a Spring application context. It shows how the reader is configured with environment, resource loader, and entity resolver, and then used to load bean definitions from specified or default configuration locations, completing a crucial part of the IOC container's initialization. ```Java XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEnvironment(getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (String configLocation : configLocations) { reader.loadBeanDefinitions(configLocation); } } } @Override protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } ``` -------------------------------- ### Telnet Command for Socket Connection Debugging Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Provides a telnet command example used to establish a socket connection to a local Netty server. This command is useful for manually testing and debugging network communication with the server. ```shell telnet 127.0.0.1 8888 ``` -------------------------------- ### Netty Server Setup with Inbound Channel Handlers Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Illustrates the setup of a Netty `ServerBootstrap` to create a TCP server. This configuration adds `InBoundHandlerA`, `OutBoundHandlerB` (as defined in the code block), and `InBoundHandlerC` to the `ChannelPipeline` for handling incoming connections and data. It binds to port 8888 and waits for the channel to close. ```Java public final class Server { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, true) .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue") .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new InBoundHandlerA()); ch.pipeline().addLast(new InBoundHandlerB()); ch.pipeline().addLast(new InBoundHandlerC()); } }); ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ``` -------------------------------- ### Dubbo ExtensionFactory SPI Configuration Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Dubbo/Dubbo底层源码学习(二)—— Dubbo的SPI机制(下).md This configuration snippet defines the SPI mappings for the `ExtensionFactory` interface in Dubbo. It specifies that 'adaptive' corresponds to `AdaptiveExtensionFactory` and 'spi' to `SpiExtensionFactory`, guiding the `ExtensionLoader` in identifying and loading the appropriate extension implementations. ```Configuration adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory ``` -------------------------------- ### AbstractConfiguredSecurityBuilder init() Method for Configurer Initialization Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/SpringSecurity/从零开始系统学习SpringSecurity和OAuth2(三)—— WebSecurity建造核心逻辑.md The `init()` method iterates through registered `SecurityConfigurer` instances, calling their `init()` methods to perform initial setup. This ensures all security configurations are properly initialized before the main configuration phase, supporting a flexible initialization process. ```Java private void init() throws Exception { // 调用getConfigurers()方法获取this.configurers的所有value值,并以List集合的形式返回 Collection> configurers = getConfigurers(); // 遍历configurers,并依次调用安全配置类的init方法 for (SecurityConfigurer configurer : configurers) { // 调用安全配置类的init初始化方法 configurer.init((B) this); } for (SecurityConfigurer configurer : configurersAddedInInitializing) { configurer.init((B) this); } } ``` -------------------------------- ### Netty DefaultChannelPipeline Core Event Propagation Methods Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Illustrates key methods in Netty's DefaultChannelPipeline responsible for propagating inbound channelRead events and initiating outbound write operations. It shows how inbound events start from the head and outbound operations from the tail. ```java public class DefaultChannelPipeline implements ChannelPipeline { ... 省略 @Override public final ChannelPipeline fireChannelRead(Object msg) { AbstractChannelHandlerContext.invokeChannelRead(head, msg); return this; } @Override public final ChannelFuture write(Object msg) { return tail.write(msg); } ... 省略 } ``` -------------------------------- ### Netty Inbound Handler Example: InBoundHandlerC Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `InBoundHandlerC`, another Netty `ChannelInboundHandlerAdapter`. Similar to `InBoundHandlerA`, it processes incoming messages by printing them and then forwarding them to the subsequent handler in the pipeline via `ctx.fireChannelRead(msg)`. ```Java public class InBoundHandlerC extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("InBoundHandlerC: " + msg); ctx.fireChannelRead(msg); } } ``` -------------------------------- ### Netty Inbound Handler Example: InBoundHandlerA Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `InBoundHandlerA`, a Netty `ChannelInboundHandlerAdapter` that processes incoming messages. It prints the received message and then propagates it to the next handler in the pipeline using `ctx.fireChannelRead(msg)`. ```Java public class InBoundHandlerA extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("InBoundHandlerA: " + msg); ctx.fireChannelRead(msg); } } ``` -------------------------------- ### Netty AbstractNioChannel Constructor Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-Netty服务端启动分析.md This constructor is a key part of Netty's channel setup. It calls the `AbstractChannel` constructor and, critically, configures the underlying `SelectableChannel` to be non-blocking (`ch.configureBlocking(false)`). This ensures that I/O operations do not block the event loop. It includes error handling for `IOException` during configuration. ```java protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { // Call the parent class AbstractChannel's constructor super(parent); this.ch = ch; this.readInterestOp = readInterestOp; try { // Close blocking, close blocking mode: very important ch.configureBlocking(false); } catch (IOException e) { try { ch.close(); } catch (IOException e2) { if (logger.isWarnEnabled()) { logger.warn( "Failed to close a partially initialized socket.", e2); } } throw new ChannelException("Failed to enter non-blocking mode.", e); } } ``` -------------------------------- ### Netty Outbound Handler Example: OutBoundHandlerB with Scheduled Write Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `OutBoundHandlerB`, a Netty `ChannelOutboundHandlerAdapter` that handles outgoing messages. It prints the message before writing it. Additionally, its `handlerAdded` method schedules a delayed write operation to the channel and context, demonstrating asynchronous operations within the pipeline. ```Java public class OutBoundHandlerB extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("OutBoundHandlerB: " + msg); ctx.write(msg, promise); } @Override public void handlerAdded(final ChannelHandlerContext ctx) { ctx.executor().schedule(() -> { ctx.channel().write("ctx.channel().write -> hello world"); ctx.write("hello world"); }, 3, TimeUnit.SECONDS); } } ``` -------------------------------- ### Netty Outbound Handler Example: OutBoundHandlerB (Write Only) Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `OutBoundHandlerB`, a Netty `ChannelOutboundHandlerAdapter` focused on handling write operations. It prints the message and then forwards the write event to the next handler in the pipeline. Note: This version only contains the `write` method, unlike the earlier `OutBoundHandlerB` which also included a `handlerAdded` method. ```Java public class OutBoundHandlerB extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("OutBoundHandlerB: " + msg); ctx.write(msg, promise); } } ``` -------------------------------- ### Netty ServerBootstrap Channel Initialization Process Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-Netty服务端启动分析.md This `init` method within `ServerBootstrap` outlines the steps to initialize a server channel. It applies user-configured channel options and attributes, both for the server channel itself and for child channels. It then configures the channel's pipeline, adding a `ChannelInitializer` that, in turn, adds the user's handler and the `ServerBootstrapAcceptor` to manage incoming connections. ```java void init(Channel channel) throws Exception { // Get user-configured options final Map, Object> options = options0(); synchronized (options) { channel.config().setOptions(options); } // Configure attrs final Map, Object> attrs = attrs0(); synchronized (attrs) { for (Entry, Object> e: attrs.entrySet()) { @SuppressWarnings("unchecked") AttributeKey key = (AttributeKey) e.getKey(); channel.attr(key).set(e.getValue()); } } ChannelPipeline p = channel.pipeline(); final EventLoopGroup currentChildGroup = childGroup; final ChannelHandler currentChildHandler = childHandler; final Entry, Object>[] currentChildOptions; final Entry, Object>[] currentChildAttrs; synchronized (childOptions) { currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); } synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); } p.addLast(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } // Add ServerBootstrapAccetor ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } }); } ``` -------------------------------- ### Spring ContextLoader: Creating and Determining WebApplicationContext Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/深入Spring源码系列(二)——深入Spring容器,通过源码阅读和时序图来彻底弄懂Spring容器(下).md This code from Spring's ContextLoader class demonstrates the core logic for instantiating a WebApplicationContext. It includes methods to determine the appropriate context class, either from servlet parameters or by defaulting to XMLWebApplicationContext, and then proceeds to create the instance, preparing it for further configuration and refresh. ```Java protected WebApplicationContext createWebApplicationContext(ServletContext sc) { // 这里判断使用什么样的类在Web容器中作为IOC容器 Class contextClass = determineContextClass(sc); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } // 直接实例化需要产生的IOC容器,并设置IOC容器的各个参数,然后通过refresh启动容器的初始化。refresh的过程相信读者并不陌生。 return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); } protected Class determineContextClass(ServletContext servletContext) { String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM); // 判断是否存在指定的IOC if (contextClassName != null) { try { return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException ex) { ... } } else { // 如果没有指定的IOC容器,则properties中获取默认的IOC容器,也就是XMLWebApplicationContext。 contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName()); try { return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader()); } catch (ClassNotFoundException ex) { ... } } } ``` -------------------------------- ### Java Strategy Pattern Demonstration Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/从Spring源码中学习——策略模式.md A demonstration class showing how to use the Strategy Pattern. It creates a 'Context' object and dynamically sets different strategy implementations (Add, Subtract, Multiply, Divide) to perform arithmetic operations, illustrating the pattern's flexibility. ```Java public class StrategyPatternDemo { public static void main(String[] args) { Context context = new Context(); context.SetStrategy(new Add()); System.out.println("10 + 5 = " + context.executeStrategy(10, 5)); context.SetStrategy(new Substract()); System.out.println("10 - 5 = " + context.executeStrategy(10, 5)); context.SetStrategy(new Multiply()); System.out.println("10 * 5 = " + context.executeStrategy(10, 5)); context.SetStrategy(new Divide()); System.out.println("10 / 5 = " + context.executeStrategy(10, 5)); } } ``` -------------------------------- ### Netty ChannelPipeline Creation in AbstractChannel Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(上).md Shows how the `ChannelPipeline` object is initialized when a new `Channel` is created. The `AbstractChannel` constructor calls `newChannelPipeline()` to instantiate a `DefaultChannelPipeline`, which then sets up the `TailContext` and `HeadContext` for the pipeline's internal linked list. ```Java protected AbstractChannel(Channel parent) { this.parent = parent; // channel的标识 id = newId(); // channel的unsafe类 // NioSocketChannel和NioServerSocketChannel的unsafe对象都一样 unsafe = newUnsafe(); // 新建pipeline pipeline = newChannelPipeline(); } protected DefaultChannelPipeline newChannelPipeline() { // 随后调用DefaultChannelPipeline对象构造方法,在构造方法中生成TailContext和HeadContext,并维护好他们的链表关系 return new DefaultChannelPipeline(this); } ``` -------------------------------- ### Netty AbstractBootstrap doBind Method for Channel Binding Logic Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-Netty服务端启动分析.md This method in Netty's `AbstractBootstrap` handles the core logic for binding a channel to a local address. It first calls `initAndRegister()` to prepare and register the channel. Depending on whether the registration future is already complete, it either directly proceeds with `doBind0` or adds a listener to the future, ensuring that `doBind0` is executed only after successful channel registration, handling potential failures gracefully. ```java private ChannelFuture doBind(final SocketAddress localAddress) { // 注册channel final ChannelFuture regFuture = initAndRegister(); final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } // regFuture如果完成了,则isDone为true,否则给regFuture添加一个监听器,当完成的时候再进行doBind0的操作 if (regFuture.isDone()) { // 此时我们已经知道NioServerSocketChannel已经完成了注册 ChannelPromise promise = channel.newPromise(); doBind0(regFuture, channel, localAddress, promise); return promise; } else { // Registration future is almost always fulfilled already, but just in case it's not. final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); // 给regFuture添加一个监听器,当注册chanel完成的时候,会回调进来 regFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { Throwable cause = future.cause(); if (cause != null) { // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an // IllegalStateException once we try to access the EventLoop of the Channel. promise.setFailure(cause); } else { // Registration was successful, so set the correct executor to use. // See https://github.com/netty/netty/issues/2586 promise.registered(); doBind0(regFuture, channel, localAddress, promise); } } }); return promise; } } ``` -------------------------------- ### Java Thread.interrupt() Method Usage Example Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/JDK/深入学习Thread底层源码.md The `interrupt()` method is used to interrupt a thread. When a thread is blocked in methods like `Object.wait()`, `Thread.join()`, or `Thread.sleep()`, calling `interrupt()` on it will cause an `InterruptedException` to be thrown, allowing the thread to exit its blocked state. This example demonstrates how a main thread can interrupt a child thread that is sleeping, causing it to catch the `InterruptedException` and terminate. ```Java @Test public void testInterrupt() throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { log.info("{} begin run",Thread.currentThread().getName()); try { log.info("子线程开始沉睡 30 s"); Thread.sleep(30000L); } catch (InterruptedException e) { log.info("子线程被打断"); e.printStackTrace(); } log.info("{} end run",Thread.currentThread().getName()); } }); // 开一个子线程去执行 thread.start(); Thread.sleep(1000L); log.info("主线程等待 1s 后,发现子线程还没有运行成功,打断子线程"); thread.interrupt(); } ``` -------------------------------- ### ChannelPipeline: ChannelOutboundInvoker Methods Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(上).md Methods inherited from `ChannelOutboundInvoker` that trigger outbound operations to be propagated through the `ChannelPipeline`, starting from the current `ChannelHandlerContext` or the tail of the pipeline. ```APID ``` -------------------------------- ### Loading Dubbo SPI Configuration Directories and Resources Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Dubbo/Dubbo底层源码学习(二)—— Dubbo的SPI机制(下).md This code demonstrates the `loadDirectory` and `loadResource` methods in Dubbo's SPI mechanism. `loadDirectory` is responsible for iterating through predefined SPI configuration directories (e.g., `META-INF/services`, `META-INF/dubbo`) and delegating to `loadResource` to process individual resource URLs. `loadResource` then loads the extension class names found in these resources, preparing them for further processing. ```Java // 加载SPI配置文件目录 private void loadDirectory(Map> extensionClasses, String dir, String type, boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) { // dir就是指的 META-INF/services、META-INF/dubbo、META-INF/dubbo/internal这三个目录 // type指的是扩展点实现类类型的全限定类名称 // fileName会拼接成:META-INF/services、META-INF/dubbo、META-INF/dubbo/internal这三个目录 + 扩展点实现类名称 String fileName = dir + type; try { // .... 省略 // 加载制定文件目录资源 loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages); // .... 省略 } } } catch (Throwable t) { // .... 省略 } } private void loadResource(Map> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL, boolean overridden, String... excludedPackages) { try { // ... 省略 // 加载扩展点的全限定类名称 loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden); // ... 省略 } catch (Throwable t) { // ... 省略 } } ``` -------------------------------- ### ChannelPipeline: ChannelInboundInvoker Methods Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(上).md Methods inherited from `ChannelInboundInvoker` that trigger inbound events to be propagated through the `ChannelPipeline`, starting from the current `ChannelHandlerContext` or the head of the pipeline. ```APIDOC ChannelInboundInvoker Interface (inherited by ChannelPipeline): fireChannelRegistered(): ChannelPipeline Triggers a channel registered event. fireChannelUnregistered(): ChannelPipeline Triggers a channel unregistered event. fireChannelActive(): ChannelPipeline Triggers a channel active event. fireChannelInactive(): ChannelPipeline Triggers a channel inactive event. fireExceptionCaught(cause: Throwable): ChannelPipeline cause: The cause of the exception. Triggers an exception caught event. fireUserEventTriggered(event: Object): ChannelPipeline event: The user event object. Triggers a user event triggered event. fireChannelRead(msg: Object): ChannelPipeline msg: The message to be read. Triggers a channel read event. fireChannelReadComplete(): ChannelPipeline Triggers a channel read complete event. fireChannelWritabilityChanged(): ChannelPipeline Triggers a channel writability changed event. ``` -------------------------------- ### Netty Outbound Handler Example: OutBoundHandlerC Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `OutBoundHandlerC`, a Netty `ChannelOutboundHandlerAdapter`. Similar to other outbound handlers, it processes outgoing write messages by printing them and then passing the write event to the subsequent handler in the pipeline. ```Java public class OutBoundHandlerC extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("OutBoundHandlerC: " + msg); ctx.write(msg, promise); } } ``` -------------------------------- ### Netty AbstractBootstrap initAndRegister Method for Channel Initialization and Registration Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-Netty服务端启动分析.md This method is crucial for creating and preparing a new Netty channel, typically a `NioServerSocketChannel` for server applications. It utilizes a `ReflectiveChannelFactory` to instantiate the channel via reflection, then calls the `init()` method to apply initial configurations. Finally, it registers the newly created and initialized channel with an `EventLoopGroup`, ensuring proper error handling and resource cleanup if the process fails. ```java final ChannelFuture initAndRegister() { Channel channel = null; try { // 拿到ReflectiveChannelFactory,然后通过其newChannel生成一个服务端Channel,底层就是通过反射newInstance()获取实例 // 这里自然是NioServerSocketChannel实例对象 channel = channelFactory.newChannel(); // 初始化channel init(channel); } catch (Throwable t) { if (channel != null) { // channel can be null if newChannel crashed (eg SocketException("too many open files")) channel.unsafe().closeForcibly(); // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t); } // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t); } /** * config() -> ServerBootstrapConfig * group() -> NioEventLoopGroup,返回的是MultithreadEventLoopGroup * register() -> 就是通过chooser选取到NioEventLoop对象 */ ChannelFuture regFuture = config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } return regFuture; } ``` -------------------------------- ### Netty Outbound Handler Example: OutBoundHandlerA Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Defines `OutBoundHandlerA`, a Netty `ChannelOutboundHandlerAdapter`. This handler intercepts outgoing write operations, prints the message, and then propagates the write event to the next outbound handler in the pipeline. ```Java public class OutBoundHandlerA extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { System.out.println("OutBoundHandlerA: " + msg); ctx.write(msg, promise); } } ``` -------------------------------- ### Dubbo ProxyFactory Adaptive Class for Dynamic Proxy Selection Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Dubbo/Dubbo底层源码学习——服务暴露.md The `ProxyFactory$Adaptive` class illustrates Dubbo's adaptive extension mechanism for proxy creation. It retrieves the `proxy` parameter from the URL, defaulting to "javassist", to dynamically load the corresponding `ProxyFactory` extension. It then delegates `getProxy` and `getInvoker` calls to the chosen proxy factory, enabling flexible proxy implementation selection at runtime. ```Java package org.apache.dubbo.rpc; import org.apache.dubbo.common.extension.ExtensionLoader; public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory { public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null"); org.apache.dubbo.common.URL url = arg0.getUrl(); // 判断如果取不到proxy,则使用默认值javassist String extName = url.getParameter("proxy", "javassist"); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])"); // 这里extension是StubProxyFactoryWrapper对象 org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName); return extension.getProxy(arg0); } public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, Boolean arg1) throws org.apache.dubbo.rpc.RpcException { if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null"); if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null"); org.apache.dubbo.common.URL url = arg0.getUrl(); String extName = url.getParameter("proxy", "javassist"); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString() + ") use keys([proxy])"); org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName); return extension.getProxy(arg0, arg1); } public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException { if (arg2 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg2; String extName = url.getParameter("proxy", "javassist"); ``` -------------------------------- ### CGLIB Proxy Enhancer and Callback Preparation in Spring AOP Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/SpringAOP/深入学习SpringAOP源码(三)——揭开JDK动态代理和CGLIB代理的神秘面纱.md This Java code snippet from `CglibAopProxy`'s `getProxy` method demonstrates the crucial steps for preparing the CGLIB `Enhancer`. It involves identifying the target class, handling existing CGLIB proxies, setting the class loader, defining the superclass and interfaces for the generated proxy, and configuring the naming policy and strategy. The snippet also shows the preparation of callbacks which will form the interceptor chain. ```Java class CglibAopProxy implements AopProxy, Serializable { public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); } try { // 获取目标代理类 Class rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class proxySuperClass = rootClass; int x; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class[] additionalInterfaces = rootClass.getInterfaces(); Class[] var5 = additionalInterfaces; int var6 = additionalInterfaces.length; for(x = 0; x < var6; ++x) { Class additionalInterface = var5[x]; this.advised.addInterface(additionalInterface); } } // 验证class this.validateClassIfNecessary(proxySuperClass, classLoader); // 获取增强器 Enhancer enhancer = this.createEnhancer(); // 为Enhancer设置类加载器 if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } // 设置代理类,这一步很关键哦。 enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // 设置strategy策略器 enhancer.setStrategy(new CglibAopProxy.ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = this.getCallbacks(rootClass); Class[] types = new Class[callbacks.length]; for(x = 0; x < types.length; ++x) { types[x] = callbacks[x].getClass(); } // 设置回调过滤器 ``` -------------------------------- ### Spring Application Context Refresh and Bean Factory Initialization Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/深入Spring源码系列(二)——深入Spring容器,通过源码阅读和时序图来彻底弄懂Spring容器(上).md This snippet shows the `refresh()` method in `AbstractApplicationContext`, which is the entry point for container startup. It then details the `finishBeanFactoryInitialization()` method, responsible for completing the bean factory's instantiation process, including initializing conversion services, adding embedded value resolvers, and pre-instantiating remaining non-lazy singletons. ```Java public void refresh() throws BeansException, IllegalStateException { ... // 实例剩余的(非懒加载)的单例 finishBeanFactoryInitialization(beanFactory); ... } /* 返程上下文bean工厂的实例化过程,实例化所有剩余的单例类 */ protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 初始化上下文的 conversion service if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 停止使用类型匹配的临时类加载器 beanFactory.setTempClassLoader(null); // 允许缓存所有bean定义元数据,而不期待进一步的更改 beanFactory.freezeConfiguration(); // 实例剩余的(非懒加载)的单例 beanFactory.preInstantiateSingletons(); } ``` -------------------------------- ### Netty Outbound Handler: handlerAdded with Scheduled Writes Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Illustrates the handlerAdded method in an OutboundHandler, demonstrating how to schedule ctx.channel().write() and ctx.write() operations. This highlights their different starting points in the pipeline for outbound event propagation. ```java @Override public void handlerAdded(final ChannelHandlerContext ctx) { ctx.executor().schedule(() -> { ctx.channel().write("ctx.channel().write -> hello world"); ctx.write("hello world"); }, 3, TimeUnit.SECONDS); } ``` -------------------------------- ### DefaultChannelPipeline Constructor Initialization Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(上).md Initializes the `DefaultChannelPipeline` with a `Channel` object, setting up `succeededFuture` and `voidPromise`. Crucially, it initializes the `head` and `tail` `AbstractChannelHandlerContext` nodes, forming the foundational doubly linked list structure of the pipeline. ```Java protected DefaultChannelPipeline(Channel channel) { // 给channel赋值channel对象 this.channel = ObjectUtil.checkNotNull(channel, "channel"); succeededFuture = new SucceededChannelFuture(channel, null); voidPromise = new VoidChannelPromise(channel, true); // 节点对象是AbstractChannelHandlerContext对象,是用于进行业务处理 // HeadContext和TailContext就是用户可以模仿实现的ChannelHandler实现类 // channelPipeline双向连表的头节点 tail = new TailContext(this); // channelPipeline双向连表的尾结点 head = new HeadContext(this); // channelPipeline: head -> tail head.next = tail; tail.prev = head; } ``` -------------------------------- ### DefaultSingletonBeanRegistry - Get Singleton from Cache Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/深入Spring源码系列(二)——深入Spring容器,通过源码阅读和时序图来彻底弄懂Spring容器(上).md Attempts to retrieve a singleton object from the cache (`singletonObjects` or `earlySingletonObjects`). This method is crucial for handling circular dependencies by allowing early references to beans currently being created. ```Java /* 尝试从缓存中获取单例对象,如果缓存中有该单例对象,并且该对象正在被创建,则从缓存中获取。 */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // singletonObjects是一个单例缓存,是一个ConcurrentHashMap Object singletonObject = this.singletonObjects.get(beanName); // 从缓存中获取单例对象、判断对象是否正在被创建 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } ``` -------------------------------- ### Netty DefaultChannelPipeline: fireChannelRead Implementation Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Netty/Netty底层源码解析-ChannelPipeline分析(下).md Details the fireChannelRead method within DefaultChannelPipeline, showing how it initiates the inbound event propagation. This method ensures that inbound events are processed sequentially starting from the pipeline's head node. ```java @Override public final ChannelPipeline fireChannelRead(Object msg) { AbstractChannelHandlerContext.invokeChannelRead(head, msg); return this; } ``` -------------------------------- ### Spring WebApplicationContext Configuration and Refresh Lifecycle Source: https://github.com/coderbruis/javasourcecodelearning/blob/master/note/Spring/深入Spring源码系列(二)——深入Spring容器,通过源码阅读和时序图来彻底弄懂Spring容器(下).md This Java method outlines the final configuration steps and the crucial refresh() call for a Spring WebApplicationContext. It covers setting the context ID, associating the ServletContext, configuring bean definition locations, initializing environment property sources, and invoking the refresh() method to fully initialize the Spring IOC container. ```Java protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) { if (ObjectUtils.identityToString(wac).equals(wac.getId())) { String idParam = sc.getInitParameter(CONTEXT_ID_PARAM); if (idParam != null) { wac.setId(idParam); } else { wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath())); } } // 设置ServletContext的引用 wac.setServletContext(sc); String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM); if (configLocationParam != null) { wac.setConfigLocation(configLocationParam); } ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(sc, null); } // 自定义上下文 customizeContext(sc, wac); // 调用SpringIOC容器的refresh()方法。 wac.refresh(); } ```