三层注解有以下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