Spring 注解驱动开发
Day 1
该课程主要讲述使用Spring注解来进行开发
注解整理
-
@Configuration
该注解标注一个类为Spring配置类,表示该类代替原始的xml配置文件
-
@ComponentScan
该注解用于配置Spring将哪些类装进IOC容器中,在注解中,参数value填写所扫描的包名,includeFilters和excludeFilters用于配置装载Bean的包含规则和过滤规则。其中有@ComponentScan.Filter注解用于配置通过某种方式进行类文件的过滤
-
@ComponentScan.Filter
该注解用在@ComponentScan的注解中的includeFilters和excludeFilters中,用于设定扫描规则共有五种规则
- FilterType.ANNOTATION //该注解通过注解类型进行过滤
- FilterType.ASSIGNABLE_TYPE//该注解通过类的类型进行过滤
- FilterType.ASPECTJ//该注解通过Aspectj的表达式,基本上不会用到
- FilterType.REGEX//该注解按照正则表达式进行匹配
- FilterType.CUSTOM//自定义规则
下面代码为FilterType.CUSTOM的使用说明
@Configuration
@ComponentScan(value = "com.lym",includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)
public class Config {
@Bean("person")
public Person person01(){
return new Person(20,"lisi");
}
}//上述类为配置类
public class MyTypeFilter implements TypeFilter {
//该类为自定义的配置类,该类需要实现TypeFilter接口
/*
* metadataReader:读取到的正在扫描的类的信息
* metadataReaderFactory 可以获取带其他任何类的信息
* */
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->" + className);
if(className.contains("er")) return true;//当类名中包含er返回true
return false;
}
}
-
@ComponentScans 该注解参数为ComponentScan[] 可用于设置多个ComponentScan
-
@Service @Controller @Respositiory @Component 以上四个个注解均为自动装配标注,如果该类在配置类的ComponentScan中的包中,那么该类的默认id为类名的第一个字母小写。但是以上四个注解只能添加在自己写的类上,对于其他的类则无可奈何
-
@Bean 用来代替xml文件中的标签,可以将组件导入IOC容器
@Bean("person")//设置id,模式是使用方法名为id,如果两处有冲突则以这里为准
public Person person01(){//默认使用方法名做id
return new Person(20,"lisi");//使用构造方法注入属性,也可以直接调用set方法注入属性
}
- @Import 快速给容器中导入一个组件
- @Import(要导入容器的组件):容器中就会自动注册这个组件,id默认是全类名。
- ImportSelector:返回需要导入的组件的全类名数组,下面介绍ImportSelector的使用方法。
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
//在Import注解中,添加MyImportSelector.class
@Configuration
@ComponentScan(value = "com.lym")
public class Config {}
public class MyImportSelector implements ImportSelector {//实现ImportSelector接口
//返回值就是导入到容器中的组件全类名
//AnnotationMetadata:当前标志@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//不能返回null,返回null会报空指针异常。
return new String[]{"com.lym.bean.Red"};
}
}
- ImportBeanDefinitionRegistrar:手动注册bean到容器中。与ImportSelector使用方法大体相似
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
//在Import注解中,添加MyImportBeanDefinitionRegistrar.class
@Configuration
@ComponentScan(value = "com.lym")
public class Config {}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/*
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry: BeanDefinition注册类:
* 把所有需要添加在容器中的bean:调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册
* */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.lym.bean.Color");
boolean definition1 = registry.containsBeanDefinition("com.lym.bean.Red");
if(definition && definition1){
//RootBeanDefinition可以指定Bean的定义信息,比如bean的作用域,bean的类型等等
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
registry.registerBeanDefinition("rainBow",rootBeanDefinition);
}
}
}
- Spring提供的FactoryBean(工厂Bean):首先创建一个工厂类,通过在Spring配置类中进行@Bean的配置,该类可以生成两种Bean,一种为工厂类中的产品类型,即实现的getObject类型的对象,另一种为工厂类本身类型,在getBean的参数加一个&前缀。
//该类需要实现FactoryBean接口,这样该类就成为了一个BeanFactory类
public class ColorFactoryBean implements FactoryBean<Color> {
//返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
//return true 这个bean是单实例,在容器中保存一份
//return false 多实例,每次获取都会创建实例
@Override
public boolean isSingleton() {
return true;
}
}
//在配置类中通过@Bean方式将此对象载入IOC容器
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");
//获得getObject返回的类型
Object colorFactoryBean = applicationContext.getBean("&colorFactoryBean");
//获得工厂类型
- @Value 在一个类标注@Component后若成员变量有默认值,则可以通过此注解在成员变量的上方标注
- @Lazy 对于单实例bean,默认在容器启动的时候创建对象,设置了懒加载模式后,第一次使用Bean的时候创建对象。
- @Scope("")
该注解设置Bean的作用域范围,常用的有两种情况,默认为singleton:单实例(默认值)单实例情况下,IOC容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是从容器中拿。
prototype:多实例 在多实例情况下IOC容器启动并不会区调用方法创建对象放在容器中,每次创建都会调用该实例所属类的构造方法。
此外还有一些SpringMVC相关联的设置。例如request,session等。
- @Conditional() 该注解可作用于方法或类上,作用为按照一定的条件进行判断,满足条件给容器注册bean,下面为具体应用案例
@Bean("bill")
@Conditional({WindowsCondition.class})
public Person person01(){
return new Person(62,"Bill Gates");
}
@Bean("linus")
@Conditional({LinuxCondition.class})
public Person person02(){
return new Person(48,"linus");
}//上面两个方法为Spring Config类中的两个Bean方法均设定了Condition
//要使用Condition,需要实现Springframework中的Condition接口
public class LinuxCondition implements Condition {
/*
* 参数说明:
* ConditionContext:判断条件能使用的上下文环境
* AnnotatedTypeMetadata :注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//是否是Linux系统
//1. 能获取到ioc使用的bean factory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2. 获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3. 获取当前环境
Environment environment = context.getEnvironment();
//4. 获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的bean注册情况,也可以给容器中注册bean
String property = environment.getProperty("os.name");
if(property.contains("linux")){
return true;
}
return false;
}
}