spring boot去除扫描自动注入依赖方法——Spring常用注解使用方法

问题:
最近做项目的时候,需要引入其他的jar。然后还需要扫描这些jar里的某些bean。于
是使用注解:@ComponentScan
这个注解直接指定包名就可以,它会去扫描这个包下所有的class,然后判断是否解析:

源码:

public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class,
        attribute = "exclude"
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class,
        attribute = "excludeName"
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}


public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}
@ComponentScan(basePackages = {"your.pkg", "other.pkg"})

public class Application {

} 

其他的jar中定义了 redissonConfig 这个bean。然后我自己的项目也定义了redissonConfig 这个bean。导致项目启动报错。所以使用如下方式,排除jar 中的RedissonConfig.class。

@ComponentScan(basePackages = {"com.xx.xx.*"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {RedissonConfig.class}))

或者

 

@SpringBootApplication(scanBasePackages = {
    "org.activiti.rest",
    "org.activiti.app.conf",
    "org.activiti.app.repository",
    "org.activiti.app.service",
    "org.activiti.app.security",
    "org.activiti.app.model.component",
    "org.activiti.engine"},
    exclude = {
        //org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
        //org.activiti.spring.boot.SecurityAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class,
        JpaRepositoriesAutoConfiguration.class, //禁止springboot自动加载持久化bean
        org.activiti.spring.boot.JpaProcessEngineAutoConfiguration.class})
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
    DatabaseConfiguration.class}))

 @ComponentScan注解。扫描或解析的bean只能是Spring内部所定义的,比如@Component、@Service、@Controller或@Repository。如果有一些自定义的注解,比如@Consumer、这个注解修饰的类是不会被扫描到的。这个时候我们就得自定义扫描器完成这个操作。

配置文件中使用的:component-scan标签底层使用ClassPathBeanDefinitionScanner这个类完成扫描工作的。@ComponentScan注解配合@Configuration注解使用,底层使用ComponentScanAnnotationParser解析器完成解析工作。

 

spring boot 启动报错

Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!

估计是跟多个数据源有关,改成如下这样就可以了
 

@SpringBootApplication  
@EnableAutoConfiguration(exclude={  
      JpaRepositoriesAutoConfiguration.class//禁止springboot自动加载持久化bean
        })  
@ImportResource({"classpath:spring-servlet.xml"})  
public class JzApplication {  
      
    public static void main(String[] args) throws Exception {  
        ApplicationContext ctx = SpringApplication.run(JzApplication .class,args);  
    }  
} 

 

目录

Spring注解开发-全面解析常用注解使用方法


github位置:https://github.com/WillVi/Spring-Annotation/

1. @Configuration

​ @Configuration //配置注解类似 applicationcontext.xml 只是将xml配置改为 注解方式进行

2. @ComponentScan

进行包扫描会根据注解进行注册组件,value="包名"

@ComponentScan(value="cn.willvi")

### FilterType

  • ANNOTATION 通过注解类型 列如 @Controller为Controller.class @Service 为 Service.class
  • ASSIGNABLE_TYPE, 一组具体类 例如PersonController.class
  • ASPECTJ, 一组表达式,使用Aspectj表达式命中类
  • REGEX 一组表达式,使用正则命中类
  • CUSTOM 自定义的TypeFilter.

excludeFilters

​ excludeFIlters = Filter[] 根据规则排除组件

@ComponentScan(value="cn.willvi",excludeFilters= {
        //根据注解排除注解类型为@Controller
        @Filter(type=FilterType.ANNOTATION,value= {Controller.class}),
        @Filter(type=FilterType.ASSIGNABLE_TYPE,value= {IncludeConfig.class,MainConfig.class}),
})

includeFilters

​ includeFIlters = Filter[] 根据规则只包含哪些组件(ps:useDefaultFilters设置为false

@ComponentScan(value="cn.willvi",includeFilters= {
        //根据注解类型扫描注解类型为@Controller的类
        @Filter(type=FilterType.ANNOTATION,value= {Controller.class})
},useDefaultFilters=false)

使用自定义TypeFilter

​ 当过滤有特殊要求时,可以实现TypeFilter来进行自定的过滤规则

自定义TypeFilter:

public class CustomTypeFilter implements TypeFilter {
    /**
     * metadataReader the metadata reader for the target class 读取当前扫描类的信息
     * metadataReaderFactory a factory for obtaining metadata readers
     * for other classes (such as superclasses and interfaces) 获取其他类的信息
     */
    public boolean match(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
        //获取当前扫描类信息
        ClassMetadata classMetadata = reader.getClassMetadata();
        //获取当前注解信息
        AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
        //获取当前类资源(类路径)
        Resource resource = reader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("----->"+className);
        if(className.contains("PersonService")) {
            return true;
        }
        return false;
    }
}

使用:

//自定义过滤组件
@ComponentScan(value="cn.willvi",includeFilters= {
        @Filter(type=FilterType.CUSTOM,value= {CustomTypeFilter.class})
},useDefaultFilters=false)
//或者
//自定义过滤组件
@ComponentScan(value="cn.willvi",excludeFilters= {
        @Filter(type=FilterType.CUSTOM,value= {CustomTypeFilter.class})})

3. @Bean

​ 注册bean与spring 的xml配置异曲同工之妙只是将xml配置转换为注解

  <bean id="person" class="cn.willvi.bean.Person"  scope="prototype" >
        <property name="age" value="23"></property>
        <property name="name" value="willvi"></property>
    </bean>

@Scope

​ 在 Spring IoC 容器是指其创建的 Bean 对象相对于其他 Bean 对象的请求可见范围。

  • singleton单例模式 全局有且仅有一个实例

  • prototype原型模式 每次获取Bean的时候会有一个新的实例

  • request 每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效

  • session session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效

  • global session global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。

    以上5个一般只用第一个和第二个

原型模式使用:

    @Bean
    @Scope("prototype")
    public Person person() {
        return new Person("willvi",23);
    }

验证:

        ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = (Person) ioc.getBean("personScope");
        Person person1 = (Person) ioc.getBean("personScope");
        //返回true说明为单例
        System.out.println(person==person1);

@Lazy

​ 懒加载。当Scope为单例模式时,当容器被初始化时就会被实例化。

​ 当有@Lazy时,在容器初始化时不会被实例化,在获取实例时才会被初始化

单例模式懒加载使用

@Bean
    @Scope
    @Lazy //去掉和加上看输出结果
    public Person person() {
        System.out.println("bean初始化");
        return new Person("willvi",23);
    }

验证:

    ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class);
    System.out.println("容器初始化完成");
    Person person = (Person) ioc.getBean("personScope");

 参考:

https://blog.csdn.net/u014252478/article/details/83831224

posted @ 2018-11-28 15:15  柚子=_=  阅读(2350)  评论(0编辑  收藏  举报