diff --git a/src/EnforcerManager.php b/src/EnforcerManager.php
index dc5da35..0c08164 100755
--- a/src/EnforcerManager.php
+++ b/src/EnforcerManager.php
@@ -7,10 +7,10 @@
 use Casbin\Model\Model;
 use Casbin\Log\Log;
 use Lauthz\Contracts\Factory;
-use Lauthz\Contracts\ModelLoader;
 use Lauthz\Models\Rule;
 use Illuminate\Support\Arr;
 use InvalidArgumentException;
+use Lauthz\Loaders\ModelLoaderManager;
 
 /**
  * @mixin \Casbin\Enforcer
@@ -87,7 +87,8 @@ protected function resolve($name)
         }
 
         $model = new Model();
-        $loader = $this->app->make(ModelLoader::class, $config);
+        $loader = $this->app->make(ModelLoaderManager::class);
+        $loader->initFromConfig($config);
         $loader->loadModel($model);
 
         $adapter = Arr::get($config, 'adapter');
diff --git a/src/LauthzServiceProvider.php b/src/LauthzServiceProvider.php
index 273f42b..84f0fb9 100644
--- a/src/LauthzServiceProvider.php
+++ b/src/LauthzServiceProvider.php
@@ -3,8 +3,7 @@
 namespace Lauthz;
 
 use Illuminate\Support\ServiceProvider;
-use Lauthz\Contracts\ModelLoader;
-use Lauthz\Loaders\ModelLoaderFactory;
+use Lauthz\Loaders\ModelLoaderManager;
 use Lauthz\Models\Rule;
 use Lauthz\Observers\RuleObserver;
 
@@ -53,8 +52,8 @@ public function register()
             return new EnforcerManager($app);
         });
 
-        $this->app->bind(ModelLoader::class, function($app, $config) {
-            return ModelLoaderFactory::createFromConfig($config);
+        $this->app->singleton(ModelLoaderManager::class, function ($app) {
+            return new ModelLoaderManager($app);
         });
     }
 }
diff --git a/src/Loaders/ModelLoaderFactory.php b/src/Loaders/ModelLoaderFactory.php
deleted file mode 100644
index 8a7ef9f..0000000
--- a/src/Loaders/ModelLoaderFactory.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-namespace Lauthz\Loaders;
-
-use Illuminate\Support\Arr;
-use Lauthz\Contracts\Factory;
-use InvalidArgumentException;
-
-class ModelLoaderFactory implements Factory
-{
-    /**
-     * Create a model loader from configuration.
-     *
-     * A model loader is responsible for a loading model from an arbitrary source.
-     * Developers can customize loading behavior by implementing
-     * the ModelLoader interface and specifying their custom class
-     * via 'model.config_loader_class' in the configuration.
-     *
-     * Built-in loader implementations include:
-     *  - FileLoader: For loading model from file.
-     *  - TextLoader: Suitable for model defined as a multi-line string.
-     *  - UrlLoader: Handles model loading from URL.
-     *
-     *  To utilize a built-in loader, set 'model.config_type' to match one of the above types.
-     *
-     * @param array $config
-     * @return \Lauthz\Contracts\ModelLoader
-     * @throws InvalidArgumentException
-     */
-    public static function createFromConfig(array $config) {
-        $customLoader = Arr::get($config, 'model.config_loader_class', '');
-        if (class_exists($customLoader)) {
-            return new $customLoader($config);
-        }
-
-        $loaderType =  Arr::get($config, 'model.config_type', '');
-        switch ($loaderType) {
-            case 'file':
-                return new FileLoader($config);
-            case 'text':
-                return new TextLoader($config);
-            case 'url':
-                return new UrlLoader($config);
-            default:
-                throw new InvalidArgumentException("Unsupported model loader type: {$loaderType}");
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/Loaders/ModelLoaderManager.php b/src/Loaders/ModelLoaderManager.php
new file mode 100644
index 0000000..623cf41
--- /dev/null
+++ b/src/Loaders/ModelLoaderManager.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Lauthz\Loaders;
+
+use Illuminate\Support\Arr;
+use Illuminate\Support\Str;
+use Illuminate\Support\Manager;
+use InvalidArgumentException;
+
+/**
+ * The model loader manager.
+ *
+ * A model loader is responsible for a loading model from an arbitrary source.
+ * Developers can customize loading behavior by implementing
+ * and register the custom loader in AppServiceProvider through `app(LoaderManager::class)->extend()`.
+ *
+ * Built-in loader implementations include:
+ *  - FileLoader: For loading model from file.
+ *  - TextLoader: Suitable for model defined as a multi-line string.
+ *  - UrlLoader: Handles model loading from URL.
+ *
+ *  To utilize a built-in or custom loader, set 'model.config_type' in the configuration to match one of the above types.
+ */
+class ModelLoaderManager extends Manager
+{
+
+    /**
+     * The array of the lauthz driver configuration.
+     * 
+     * @var array
+     */
+    protected $config;
+
+    /**
+     * Initialize configuration for the loader manager instance.
+     *
+     * @param array $config the lauthz driver configuration.
+     */
+    public function initFromConfig(array $config)
+    {
+        $this->config = $config;
+    }
+
+    /**
+     * Get the default driver from the configuration.
+     *
+     * @return string The default driver name.
+     */
+    public function getDefaultDriver()
+    {
+        return Arr::get($this->config, 'model.config_type', '');
+    }
+
+    /**
+     * Create a new TextLoader instance.
+     *
+     * @return TextLoader
+     */
+    public function createTextDriver()
+    {
+        return new TextLoader($this->config);
+    }
+
+    /**
+     * Create a new UrlLoader instance.
+     *
+     * @return UrlLoader
+     */
+    public function createUrlDriver()
+    {
+        return new UrlLoader($this->config);
+    }
+
+    /**
+     * Create a new FileLoader instance.
+     *
+     * @return FileLoader
+     */
+    public function createFileDriver()
+    {
+        return new FileLoader($this->config);
+    }
+
+    /**
+     * Create a new driver instance.
+     *
+     * @param  string  $driver
+     * @return mixed
+     *
+     * @throws \InvalidArgumentException
+     */
+    protected function createDriver($driver)
+    {
+        if(empty($driver)) {
+            throw new InvalidArgumentException('Unsupported empty model loader type.');
+        }
+
+        if (isset($this->customCreators[$driver])) {
+            return $this->callCustomCreator($driver);
+        }
+        $method = 'create' . Str::studly($driver) . 'Driver';
+        if (method_exists($this, $method)) {
+            return $this->$method();
+        }
+
+        throw new InvalidArgumentException("Unsupported model loader type: {$driver}.");
+    }
+}
diff --git a/tests/DatabaseAdapterTest.php b/tests/DatabaseAdapterTest.php
index 195c35b..21b13c7 100644
--- a/tests/DatabaseAdapterTest.php
+++ b/tests/DatabaseAdapterTest.php
@@ -309,7 +309,7 @@ public function testLoadFilteredPolicy()
         $this->assertEquals([
             ['bob', 'data2', 'write']
         ], Enforcer::getPolicy());
-        
+
         // Filter
         $filter = new Filter(['v2'], ['read']);
         Enforcer::loadFilteredPolicy($filter);
diff --git a/tests/ModelLoaderTest.php b/tests/ModelLoaderTest.php
index 75a93f3..4d673d5 100644
--- a/tests/ModelLoaderTest.php
+++ b/tests/ModelLoaderTest.php
@@ -3,6 +3,7 @@
 namespace Lauthz\Tests;
 
 use Lauthz\Facades\Enforcer;
+use Lauthz\Loaders\ModelLoaderManager;
 use InvalidArgumentException;
 use RuntimeException;
 
@@ -67,7 +68,15 @@ public function testEmptyLoaderType(): void
         $this->assertFalse(Enforcer::enforce('alice', 'data', 'read'));
     }
 
-    public function testBadUlrConnection(): void
+    public function testNotExistLoaderType(): void
+    {
+        $this->app['config']->set('lauthz.basic.model.config_type', 'not_exist');
+        $this->expectException(InvalidArgumentException::class);
+
+        $this->assertFalse(Enforcer::enforce('alice', 'data', 'read'));
+    }
+
+    public function testBadUrlConnection(): void
     {
         $this->initUrlConfig();
         $this->app['config']->set('lauthz.basic.model.config_url', 'http://filenoexists');
@@ -94,12 +103,20 @@ protected function initTextConfig(): void
         );
     }
 
-    protected function initCustomConfig(): void {
-        $this->app['config']->set('lauthz.second.model.config_loader_class', '\Lauthz\Loaders\TextLoader');
+    protected function initCustomConfig(): void
+    {
+        $this->app['config']->set('lauthz.second.model.config_type', 'custom');
         $this->app['config']->set(
             'lauthz.second.model.config_text',
             $this->getModelText()
         );
+
+        $config = $this->app['config']->get('lauthz.second');
+        $loader = $this->app->make(ModelLoaderManager::class);
+
+        $loader->extend('custom', function () use ($config) {
+            return new \Lauthz\Loaders\TextLoader($config);
+        });
     }
 
     protected function getModelText(): string
@@ -118,4 +135,4 @@ protected function getModelText(): string
 m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
 EOT;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/RequestMiddlewareTest.php b/tests/RequestMiddlewareTest.php
index b4e6088..0805952 100644
--- a/tests/RequestMiddlewareTest.php
+++ b/tests/RequestMiddlewareTest.php
@@ -5,6 +5,7 @@
 use Lauthz\Middlewares\RequestMiddleware;
 use Illuminate\Foundation\Testing\DatabaseMigrations;
 use Illuminate\Http\Request;
+use Lauthz\Facades\Enforcer;
 use Lauthz\Models\Rule;
 
 class RequestMiddlewareTest extends TestCase
@@ -34,11 +35,19 @@ public function testAfterLogin()
         $this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT')), 'Unauthorized Exception');
 
         $this->assertEquals($this->middleware(Request::create('/proxy', 'GET')), 'Unauthorized Exception');
+        
+        Enforcer::guard('second')->addPolicy('alice', '/foo1/*', '(GET|POST)');
+
+        $this->assertEquals($this->middleware(Request::create('/foo1/123', 'GET'), 'second'), 200);
+        $this->assertEquals($this->middleware(Request::create('/foo1/123', 'POST'), 'second'), 200);
+        $this->assertEquals($this->middleware(Request::create('/foo1/123', 'PUT'), 'second'), 'Unauthorized Exception');
+
+        $this->assertEquals($this->middleware(Request::create('/proxy', 'GET'), 'second'), 'Unauthorized Exception');
     }
 
-    protected function middleware($request)
+    protected function middleware($request, ...$guards)
     {
-        return parent::runMiddleware(RequestMiddleware::class, $request);
+        return parent::runMiddleware(RequestMiddleware::class, $request, ...$guards);
     }
 
     protected function initConfig()
@@ -62,6 +71,8 @@ protected function initConfig()
 m = g(r.sub, p.sub) && r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
 EOT;
         $this->app['config']->set('lauthz.basic.model.config_text', $text);
+        $this->app['config']->set('lauthz.second.model.config_type', 'text');
+        $this->app['config']->set('lauthz.second.model.config_text', $text);
     }
 
     protected function initTable()