исключить @component из @componentscan

<p>у меня есть компонент, который я хочу исключить из <code>@componentscan</code> в конкретном <code>@configuration</code>:</p><pre><code>@component("foo") class foo { ... } </code></pre><p>в противном случае, это похоже на конфликт с каким-то другим классом в моем проекте. я не до конца понимаю коллизию, но если я закомментирую аннотацию <code>@component</code>, все будет работать так, как я хочу. но другие проекты, использующие эту библиотеку, ожидают, что этим классом будет управлять spring, поэтому я хочу пропустить его только в своем проекте.</p><p>я пытался использовать <code>@componentscan.filter</code>:</p><pre><code>@configuration @enablespringconfigured @componentscan(basepackages = {"com.example"}, excludefilters={ @componentscan.filter(type=filtertype.assignable\_type, value=foo.class)}) public class myspringconfiguration {} </code></pre><p>но это не похоже на работу. если я пытаюсь использовать <code>filtertype.assignable\_type</code>, я получаю странную ошибку из-за невозможности загрузить какой-то, казалось бы, случайный класс:</p><blockquote> <p>причина: java.io.filenotfoundexception: ресурс пути к классу [junit/framework/testcase.class] не может быть открыт, потому что он не существует</p> </blockquote><p>я также попытался использовать <code>type=filtertype.custom</code> следующим образом:</p><pre><code>class excludefoofilter implements typefilter { @override public boolean match(metadatareader metadatareader, metadatareaderfactory metadatareaderfactory) throws ioexception { return metadatareader.getclass() == foo.class; } } @configuration @enablespringconfigured @componentscan(basepackages = {"com.example"}, excludefilters={ @componentscan.filter(type=filtertype.assignable\_type, value=foo.class)}) public class myspringconfiguration {} </code></pre><p>но это, кажется, не исключает компонент из сканирования, как я хочу.</p><p>как мне это исключить?</p>

<p>конфигурация выглядит нормально, за исключением того, что вы должны использовать <code>excludefilters</code> вместо <code>excludes</code>:</p><pre><code>@configuration @enablespringconfigured @componentscan(basepackages = {"com.example"}, excludefilters={ @componentscan.filter(type=filtertype.assignable\_type, value=foo.class)}) public class myspringconfiguration {} </code></pre>

<p>использование явных типов в фильтрах сканирования для меня ужасно. я считаю, что более элегантный подход заключается в создании собственной аннотации маркера:</p><pre><code>public @interface ignoreduringscan { } </code></pre><p>отметьте компонент, который должен быть исключен с ним:</p><pre><code>@component("foo") @ignoreduringscan class foo { ... } </code></pre><p>и исключите эту аннотацию из вашего сканирования компонентов:</p><pre><code>@componentscan(excludefilters = @filter(ignoreduringscan.class)) public class myspringconfiguration {} </code></pre>

<p>другой подход заключается в использовании новых условных аннотаций . поскольку<strong> plain </strong>spring 4, вы можете использовать @conditional аннотацию:</p><pre><code>@component("foo") @conditional(foocondition.class) class foo { ... } </code></pre><p>и определить условную логику для регистрации компонента foo:</p><pre><code>public class foocondition implements condition{ @override public boolean matches(conditioncontext context, annotatedtypemetadata metadata) { // return [your conditional logic] } } </code></pre><p>условная логика может основываться на контексте, потому что у вас есть доступ к фабрике бинов. например, когда компонент "bar" не зарегистрирован как компонент:</p><pre><code> return !context.getbeanfactory().containsbean(bar.class.getsimplename()); </code></pre><p><strong> с spring boot (должен использоваться для каждого нового проекта spring), вы можете использовать эти условные аннотации: </strong></p><ul> <li><code>@conditionalonbean</code></li> <li><code>@conditionalonclass</code></li> <li><code>@conditionalonexpression</code></li> <li><code>@conditionalonjava</code></li> <li><code>@conditionalonmissingbean</code></li> <li><code>@conditionalonmissingclass</code></li> <li><code>@conditionalonnotwebapplication</code></li> <li><code>@conditionalonproperty</code></li> <li><code>@conditionalonresource</code></li> <li><code>@conditionalonwebapplication</code></li> </ul><p>таким способом вы можете избежать создания класса condition. обратитесь к документации spring boot для более подробной информации.</p>

<p>в случае, если вам нужно определить два или более<em> excludefilters </em>критерия, вы должны использовать массив. </p><p>для экземпляров в этом разделе кода я хочу исключить все классы в пакете<em> org.xxx.yyy </em>и другой определенный класс,<em> myclasstoexclude </em></p><pre><code> @componentscan( excludefilters = { @componentscan.filter(type = filtertype.regex, pattern = "org.xxx.yyy.*"), @componentscan.filter(type = filtertype.assignable\_type, value = myclasstoexclude.class) }) </code></pre>

<p>у меня возникла проблема при использовании <strong>@configuration</strong>, <strong>@enableautoconfiguration</strong> и <strong>@componentscan</strong> при попытке исключить определенные классы конфигурации, дело в том, что это не сработало! </p><p>в конце концов я решил эту проблему с помощью <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html"><strong>@springbootapplication</strong></a> , который в соответствии с документацией spring выполняет те же функции, что и три выше в одной аннотации.</p><p>другой совет - сначала попробуйте без уточнения сканирования вашего пакета (без фильтра basepackages).</p><pre><code>@springbootapplication(exclude= {foo.class}) public class myspringconfiguration {} </code></pre>

<p>в случае исключения тестового компонента или тестовой конфигурации spring boot 1.4 вводит новые аннотации тестирования <a href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-excluding-config"><code>@testcomponent</code> и <code>@testconfiguration</code></a> .</p>

<p>мне нужно было исключить аудит @aspect @component из контекста приложения, но только для нескольких тестовых классов. я закончил тем, что использовал @profile ("аудит") в классе аспектов; включая профиль для обычных операций, но исключая его (не помещайте его в @activeprofiles) для определенных тестовых классов.</p>