Spring三层注解加扫描器的使用

三层注解有以下4类:

注解描述
@Service用于service
@Repository用于dao层
@Controller用于控制器层
@Component以上的三种都可以用该注解代替

使用时只需要在对应的类前面加上注解,再配置扫描器即可:

@Service 
//@Repository
//@Controller
//@Component
public class W{
	...
}

现在讲述怎么配置扫描器:
xml形式:只需要在context:component-scan标签体中package中指定对应的包

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--扫描器-->
    <context:component-scan base-package="xxxxx,yyyy">
    </context:component-scan>

</beans>

配置类的方式:

@Configuration
//@ComponentScan(value = "luzelong.service,luzelong.dao,luzelong.controller")
@ComponentScan(value = "luzelong")
//@ComponentScan(value = "luzelong",includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value={Service.class,Repository.class})},useDefaultFilters=false)//包含
//@ComponentScan(value = "luzelong",excludeFilters={@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class, Repository.class})})//排除
//@ComponentScan(value = "luzelong",includeFilters={@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,value={StudentController.class})},useDefaultFilters=false)
//@ComponentScan(value = "luzelong",includeFilters={@ComponentScan.Filter(type= FilterType.CUSTOM,value={MyFilter.class})},useDefaultFilters = false)//包含  CUSTOM自定义规则
public class MyConfig {
	......
}

1.@ComponentScan(value = “luzelong”) value中直接写包名,多个包用逗号隔开即可
2.如果想排除某些包就得指定属性excludeFilters
@ComponentScan(value = “luzelong”,excludeFilters={@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class, Repository.class})})
上面的这种就排除了Service和Repository注解的类
3.如果想要只包含包中的某些类就得指定属性includeFilters
只选出Service和Repository注解的类
@ComponentScan(value = “luzelong”,includeFilters={@ComponentScan.Filter(type=FilterType.ANNOTATION,value={Service.class,Repository.class})},useDefaultFilters=false)
只选出特定的类(StudentController):
@ComponentScan(value = “luzelong”,includeFilters={@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,value={StudentController.class})},useDefaultFilters=false)
4.也可以写一个专门的过滤类来指定,注意下面type改成了CUSTOM,value指定的是过滤类

@ComponentScan(value = “luzelong”,includeFilters={@ComponentScan.Filter(type= FilterType.CUSTOM,value={MyFilter.class})},useDefaultFilters = false)
过滤类:

package config;

import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class MyFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //扫描器扫描"luzelong"包中所有的类,getClassName()可以拿到该包中 所有标有三层注解类的名字
        String className = classMetadata.getClassName();
        if(className.contains("School")) return true;
        else return false;
    }
}

不过配置类还有两种特殊的注入方式:

1.@Import注解方式:(不需要扫描器,强行直接导入)

@Configuration
//@Import({Apple.class,Banana.class})//通过import方式加入bean 并且id值是全类名
//@Import({MyImportSelector.class})//通过接口selector的import方法
//@Import({MyImportSelector.class,Orange.class})//甚至可以联合用
//@Import({MyimportBeanDefinitionRegistrar.class})//通过接口ImportBeanDefinitionRegistrar的import方法
public class MyConfig {
	...
}

selector的编写:

package config;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //返回值就是 要加入IOC容器的Bean的全类名
        return new String[]{"entity.Apple","entity.Banana"};
    }
}

实现ImportBeanDefinitionRegistrar的方法:

package config;

import entity.Orange;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyimportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition rootBeanDefinition = new RootBeanDefinition(Orange.class);
//        BeanDefinition rootBeanDefinition = new RootBeanDefinition("entity.Orange");
        registry.registerBeanDefinition("myorange",rootBeanDefinition);//id class
    }
}

2.写一个继承FactoryBean的bean 并将该类手写进ioc

package config;

import entity.Apple;
import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Apple();
    }

    @Override
    public Class<?> getObjectType() {
        return Apple.class;
    }

    @Override//是否需要用单例模式
    public boolean isSingleton() {
        return true;
    }
}

ioc:

public class MyConfig {
   @Bean
    public FactoryBean<Apple> myFactoryBean(){
        return new MyFactoryBean();
    }
}

注意:这种方式有别于直接将Apple类直接写成bean

public class test{
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        Object obj1 = context.getBean("myFactoryBean");
        Object obj2 = context.getBean("&myFactoryBean");
        System.out.println(obj1);
        System.out.println(obj2);
    }
	}
}

obj1:不加&,获取的是最内部真实的Apple;
obj2: 如果加了&,获取的 是FacotryBean

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

键盘歌唱家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值