Spring注解开发
-
启动注解扫描
<context:component-scan base-package="包名"</context:component-scan>
- 说明:
- 对包和其子包扫描
- 递归扫描
- 只扫描合法java文件
- 只读取spring识别的注解
- 扫描后把资源放到IOC容器
- @ComponentScan(“注解扫描的包名”)
- 说明:
-
bean的注解定义
- @Component @Controller @Service @Repository
-
存在大量的bean时,需要高效的配置大量bean的方式:自定义导入器
-
实现一个接口:ImportSelector
-
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; import java.util.ResourceBundle; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 1.编程形式加载一个类 // return new String[]{"com.itheima.dao.impl.BookDaoImpl"}; // 2.加载import.properties文件中的单个类名 // ResourceBundle bundle = ResourceBundle.getBundle("import"); // String className = bundle.getString("className"); // 3.加载import.properties文件中的多个类名 ResourceBundle bundle = ResourceBundle.getBundle("import"); String className = bundle.getString("className"); return className.split(","); } }
-
上诉代码中的import.properties的文件内容
-
#2.加载import.properties文件中的单个类名 #className=com.itheima.dao.impl.BookDaoImpl #3.加载import.properties文件中的多个类名 #className=com.itheima.dao.impl.BookDaoImpl,com.itheima.dao.impl.AccountDaoImpl
-
-
-
上诉代码中,需要一条一条的写包名,下面是直接写路径名方法
-
import.properties中的内容
-
path=com.itheima.dao.impl.*
-
-
-
package config.selector; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AspectJTypeFilter; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; public class CustomerImportSelector implements ImportSelector { private String expression; public CustomerImportSelector(){ try { //初始化时指定加载的properties文件名 Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties"); //设定加载的属性名 expression = loadAllProperties.getProperty("path"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { //1.定义扫描包的名称 String[] basePackages = null; //2.判断有@Import注解的类上是否有@ComponentScan注解 if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) { //3.取出@ComponentScan注解的属性 Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName()); //4.取出属性名称为basePackages属性的值 basePackages = (String[]) annotationAttributes.get("basePackages"); } //5.判断是否有此属性(如果没有ComponentScan注解则属性值为null,如果有ComponentScan注解,则basePackages默认为空数组) if (basePackages == null || basePackages.length == 0) { String basePackage = null; try { //6.取出包含@Import注解类的包名 basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName(); } catch (ClassNotFoundException e) { e.printStackTrace(); } //7.存入数组中 basePackages = new String[] {basePackage}; } //8.创建类路径扫描器 ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); //9.创建类型过滤器(此处使用切入点表达式类型过滤器) TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader()); //10.给扫描器加入类型过滤器 scanner.addIncludeFilter(typeFilter); //11.创建存放全限定类名的集合 Set<String> classes = new HashSet<>(); //12.填充集合数据 for (String basePackage : basePackages) { scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName())); } //13.按照规则返回 return classes.toArray(new String[classes.size()]); } }
-
-
bean的作用域
- @Scope(默认单例)
注解开发第三方资源
- @Bean
- 定义在方法上
- 设置该方法的返回值最为spring管理的bean
注解的属性注入
-
@Value
- 属性定义的上方,方法定义的上方
- 对数学或方法进行传参
- 只支持非引用类型
- 支持读取properties文件的属性值
-
@Autowired
- 按类型自动匹配注入引用类型(若类型一样,按注解的变量名来匹配)
-
@Qualifier
- 指定注入的id
- 需要和Autowired配合使用
注解的properties文件读取
@PropertySource("classpath:jdbc.properties")
//不支持*.properties
//多个文件可以用{"",""}这样的形式
注解的spring核心配置类
用spring核心配置类取代applicationContext.xml文件
@Configuration
//注解扫描bean
@ComponentScan("注解扫描的包名")
//开发过程中,根据需求加载指定bean,排除其他bean
@ComponentScan(value = "注解扫描的包名",
excludeFilters = @ComponentScan.File(
type = FilterType.ANNOTATION,
classes = Service.class
)
)
//自己定义一个过滤规则,来过滤扫描文件。例如:MyFilter这个类,此类要实现TypeFilter接口,这个实现的接口方法返回true就过滤掉这个方法
@ComponentScan(value = "注解扫描的包名",
excludeFilters = @ComponentScan.File(
type = FilterType.CUSTOM,
classes = MyTypeFilter.class
)
)
//导入第三方资源的配置类,多个就用数组数组
@Import(JDBCCONFIG.class)
public class SpringConfigClassName{
}
//纯注解开发,加载spring上下文对象需要使用的对象是:
//AnnotationConfigApplicationContext