# Services - Vapor Docs

Skip to content


# Using Services

This guide will show you how to register, configure, and create your own service. In this example we will be assuming two different `Logger` implementations.

- `PrintLogger`: Prints logs.
- `FileLogger`: Saves logs to a file. Already conforms to `ServiceType`.

## Register

Let's take a look at how we can register our `PrintLogger`. First you must conform your type to `Service`. The easiest way to do this is simply adding the conformance in an extension.

    extension PrintLogger: Service { }

It's an empty protocol so there should be no missing requirements.

### Factory

Now the service can be registered to the `Services` struct. This is usually done in `configure.swift`.

    services.register(Logger.self) { container in
        return PrintLogger()
    }

By registering the `PrintLogger` using a factory (closure) method, we allow the `Container` to dynamically create the service once it is needed. Any `SubContainer`s created later can call this method again to create their own `PrintLogger`s.

### Service Type

To make registering a service easier, you can conform it to `ServiceType`.

    extension PrintLogger: ServiceType {
        /// See `ServiceType`.
        static var serviceSupports: [Any.Type] {
            return [Logger.self]
        }

        /// See `ServiceType`.
        static func makeService(for worker: Container) throws -> PrintLogger {
            return PrintLogger()
        }
    }

Services conforming to `ServiceType` can be registered using just the type name. This will automatically conform to `Service` as well.

    services.register(PrintLogger.self)

### Instance

You can also register pre-initialized instances to `Services`.

    services.register(PrintLogger(), as: Logger.self)

Warning

If using reference types (`class`) this method will share the same object between all `Container`s and `SubContainer`s. Be careful to protect against race conditions.

## Configure

If more than one service is registered for a given interface, we will need to choose which service is used.

    services.register(PrintLogger.self)
    services.register(FileLogger.self)

Assuming the above services are registered, we can use service `Config` to pick which one we want.

    switch env {
    case .production: config.prefer(FileLogger.self, for: Logger.self)
    default: config.prefer(PrintLogger.self, for: Logger.self)
    }

Here we are using the `Environment` to dynamically prefer a service. This is usually done in `configure.swift`.

Note

You can also dynamically register services based on environment instead of using service config. However, service config is required for choosing services that come from the framework or a provider.

## Create

After you have registered your services, you can use a `Container` to create them.

    let logger = try someContainer.make(Logger.self)
    logger.log("Hello, world!")

    // PrintLogger or FileLogger depending on the container's environment
    print(type(of: logger))

Tip

Usually the framework will create any required containers for you. You can use `BasicContainer` if you want to create one for testing.

## Comments