8000 Lazy services - service proxies by Ocramius · Pull Request #7527 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Lazy services - service proxies #7527

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f503ad8
First implementation of lazy services via proxy manager
Ocramius Mar 29, 2013
67aef45
Adding basic logic to generate proxy instantiation into a php dumped …
Ocramius Mar 30, 2013
f4a19c7
Compiling proxies into the generated DIC file
Ocramius Mar 30, 2013
d2760f1
Upgrading dependency to ProxyManager 0.3.*
Ocramius Mar 30, 2013
4a13f82
Suggesting ProxyManager in composer.json, removing useless calls
Ocramius Mar 31, 2013
a6a6572
Adding failing test to demonstrate that proxy initialization breaks s…
Ocramius Mar 31, 2013
35fdded
Fixing shared service instance
Ocramius Mar 31, 2013
bec7774
Sharing services in the container should only happen when proxying fa…
Ocramius Mar 31, 2013
468e92e
Adding tests for proxy sharing within dumped containers
Ocramius Mar 31, 2013
4ecd5ad
Fixing shared proxies into the container
Ocramius Mar 31, 2013
11a1da9
Bumping required version of ProxyManager
Ocramius Mar 31, 2013
5870fed
Docblock for ContainerBuilder#shareService
Ocramius Mar 31, 2013
695e3c5
Adding `ContainerBuilder#addClassResource`
Ocramius Mar 31, 2013
c5a5af0
Adding test to check that class resources are registered for lazy ser…
Ocramius Apr 1, 2013
29899ec
Fixing tests, registering class resources for lazy services
Ocramius Apr 1, 2013
b5d0298
Reverting import of global namespace classes
Ocramius Apr 2, 2013
cda390b
Lazier checks on the proxy structure (avoiding whitespace-based test …
Ocramius Apr 25, 2013
1eb4cf7
Getters for proxied services are public for 5.3.3 compatibility
Ocramius Apr 25, 2013
b417969
Enforcing soft dependency to ProxyManager
Ocramius Apr 25, 2013
1e24767
Reverting documentation changes, adding exception types description i…
Ocramius Apr 25, 2013
450635a
Lazier checks on the proxy structure
Ocramius Apr 27, 2013
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
8000
Diff view
Next Next commit
First implementation of lazy services via proxy manager
  • Loading branch information
Ocramius committed Apr 30, 2013
commit f503ad8026457d91a503c86f6113589be1183db4
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"symfony/yaml": "self.version"
},
"require-dev": {
"ocramius/proxy-manager": "0.2.*",
"doctrine/data-fixtures": "1.0.*",
"doctrine/dbal": "~2.2",
"doctrine/orm": "~2.2,>=2.2.3",
Expand Down
19 changes: 18 additions & 1 deletion src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

namespace Symfony\Component\DependencyInjection;

use ProxyManager\Configuration;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
Expand Down Expand Up @@ -873,8 +876,22 @@ public function findDefinition($id)
* @throws RuntimeException When the service is a synthetic service
* @throws InvalidArgumentException When configure callable is not callable
*/
private function createService(Definition $definition, $id)
public function createService(Definition $definition, $id, $tryProxy = true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to update the phpdoc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And you should add @internal in the phpdoc to explain that it is only public because of the internal use in a closure, and should not be called by other code

{
if ($tryProxy && ($className = $definition->getClass()) && $definition->isLazy()) {
$factory = new LazyLoadingValueHolderFactory(new Configuration());
$container = $this;

return $factory->createProxy(
$className,
function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $definition, $id) {
$proxy->setProxyInitializer(null);

$wrappedInstance = $container->createService($definition, $id, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the call to createService replace the shared instance ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this has also a test for it, see ContainerBuilderTest:276, where I explicitly check:

$this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved after initialization'); 

}
);
}

if ($definition->isSynthetic()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done before creating the lazy proxy IMO.

throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
}
Expand Down
30 changes: 30 additions & 0 deletions src/Symfony/Component/DependencyInjection/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Definition
private $synthetic;
private $abstract;
private $synchronized;
private $lazy;

protected $arguments;

Expand All @@ -58,6 +59,7 @@ public function __construct($class = null, array $arguments = array())
$this->public = true;
$this->synthetic = false;
$this->synchronized = false;
$this->lazy = false;
$this->abstract = false;
$this->properties = array();
}
Expand Down Expand Up @@ -599,6 +601,34 @@ public function isSynchronized()
return $this->synchronized;
}

/**
A3DB * Sets the lazy flag of this service.
*
* @param Boolean $lazy
*
* @return Definition The current instance
*
* @api
*/
public function setLazy($lazy)
{
$this->lazy = (Boolean) $lazy;

return $this;
}

/**
* Whether this service is lazy.
*
* @return Boolean
*
* @api
*/
public function isLazy()
{
return $this->lazy;
}

/**
* Sets whether this definition is synthetic, that is not constructed by the
* container, but dynamically injected.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ private function addService($definition, $id, \DOMElement $parent)
if ($definition->isSynchronized()) {
$service->setAttribute('synchronized', 'true');
}
if ($definition->isLazy()) {
$service->setAttribute('lazy', 'true');
}

foreach ($definition->getTags() as $name => $tags) {
foreach ($tags as $attributes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ private function addService($id, $definition)
$code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass());
}

if ($definition->isLazy()) {
$code .= sprintf(" lazy: true\n");
}

if ($definition->getFactoryMethod()) {
$code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private function parseDefinition($id, $service, $file)
$definition = new Definition();
}

foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'abstract') as $key) {
foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) {
if (isset($service[$key])) {
$method = 'set'.str_replace('-', '', $key);
$definition->$method((string) $service->getAttributeAsPhp($key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ private function parseDefinition($id, $service, $file)
$definition->setSynchronized($service['synchronized']);
}

if (isset($service['lazy'])) {
$definition->setLazy($service['lazy']);
}

if (isset($service['public'])) {
$definition->setPublic($service['public']);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
<xsd:attribute name="public" type="boolean" />
<xsd:attribute name="synthetic" type="boolean" />
<xsd:attribute name="synchronized" type="boolean" />
<xsd:attribute name="lazy" type="boolean" />
<xsd:attribute name="abstract" type="boolean" />
<xsd:attribute name="factory-class" type="xsd:string" />
<xsd:attribute name="factory-method" type="xsd:string" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,30 @@ public function testCreateService()
$this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition');
}

/**
* @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
*/
public function testCreateServiceWithDelegateFactory()
{
$builder = new ContainerBuilder();

$builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
$builder->getDefinition('foo1')->setLazy(true);

/* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */
$foo1 = $builder->get('foo1');

$this->assertInstanceOf('\FooClass', $foo1);
$this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1);
$this->assertFalse($foo1->isProxyInitialized());

$foo1->initializeProxy();

$this->assertTrue($foo1->isProxyInitialized());
$this->assertInstanceOf('\FooClass', $foo1->getWrappedValueHolderValue());
$this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue());
}

/**
* @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
*/
Expand Down
12 changes: 12 additions & 0 deletions src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ public function testSetIsSynchronized()
$this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.');
}

/**
* @covers Symfony\Component\DependencyInjection\Definition::setLazy
* @covers Symfony\Component\DependencyInjection\Definition::isLazy
*/
public function testSetIsLazy()
{
$def = new Definition('stdClass');
$this->assertFalse($def->isLazy(), '->isLazy() returns false by default');
$this->assertSame($def, $def->setLazy(true), '->setLazy() implements a fluent interface');
$this->assertTrue($def->isLazy(), '->isLazy() returns true if the service is lazy.');
}

/**
* @covers Symfony\Component\DependencyInjection\Definition::setAbstract
* @covers Symfony\Component\DependencyInjection\Definition::isAbstract
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@
<service id="alias_for_foo" alias="foo" />
<service id="another_alias_for_foo" alias="foo" public="false" />
<service id="factory_service" factory-method="getInstance" factory-service="baz_factory" />
<service id="request" class="Request" synthetic="true" synchronized="true"/>
<service id="request" class="Request" synthetic="true" synchronized="true" lazy="true"/>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ services:
class: Request
synthetic: true
synchronized: true
lazy: true
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public function testLoadServices()

$this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
$this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
$this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

$aliases = $container->getAliases();
$this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses <service> elements');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public function testLoadServices()

$this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
$this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
$this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

$aliases = $container->getAliases();
$this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases');
Expand Down
0