Spring常用注解(绝对经典)
1、需要导入的spring框架的依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version></dependency>
2、@Configuration
设置类为配置类
3、AnnotationConfigApplicationContext
- 通过配置类获取上下文环境applicationContext
- 可以通过getBeanDefinitionNames()获得配置类中配置的各类Bean
- 也可以使用getBeanNamesForType()通过类型来获得bean的name(id)
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String str : beanDefinitionNames) {System.out.println(str);}
4、@Bean
- 注册一个javaBean
- 默认用方法名作为Bean的id
- 使用AnnotationConfigApplicationContext的实例 通过getBean来获得这个Bean
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {@Beanpublic Person person(){return new Person("lisi",20);}
}
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);Person bean = applicationContext.getBean(Person.class);System.out.println(bean);
5、@ComponentScan
为配置类开启组件扫描
- 放在配置类的上方,指定扫描的包路径如
@ComponentScan(value = "com.atguigu")
- 还可以使用excludeFilter来设置类扫描规则如包含、排除,excludeFilter需要设置为一个数组
排除
包含使用excludeFilter,并为其设置一个过滤数组,来指定需要过滤掉那些组件
@Configuration
@ComponentScan(value = "com.atguigu",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes ={Controller.class,Service.class} )
})
public class MainConfig {@Beanpublic Person person(){return new Person("lisi",20);}
}
包含
包含使用includeFilter,包含里面需要设置使用默认规则为false
@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes ={Controller.class,Service.class} )},useDefaultFilters = false)
public class MainConfig {@Beanpublic Person person(){return new Person("lisi",20);}
}
还可以设置按给定类型过滤
@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes ={Controller.class,Service.class}),@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes ={BookService.class})
},useDefaultFilters = false)
public class MainConfig {@Beanpublic Person person(){return new Person("lisi",20);}
}
其他可以设置的过滤方式还可以有:
- 使用FilterType.ASPECTJ按照ASPECTJ表达式
- 使用FilterType.REGEX按照REGEX正则表达式
- 使用FilterType.CUSTOM按照自定义规则过滤(需要实现TypeFilter接口)
自定义过滤规则
public class MyTypeFilter implements TypeFilter {/*metadataReader:读取到的当前正在扫描的类的信息metadataReaderFactory:可以获取到其他任何类的信息*/@Overridepublic 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(resource);System.out.println(className);if(className.contains("er")){return true;}return false;}
}
设置自定义规则
@Configuration
@ComponentScan(value = "com.atguigu",includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false)
public class MainConfig {@Beanpublic Person person(){return new Person("lisi",20);}
}
测试代码
@Testpublic void testbeans() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String str : beanDefinitionNames) {System.out.println(str);}}
测试结果
测试规则打印内容
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/bean/Person.class]
com.atguigu.bean.Person
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/config/MyTypeFilter.class]
com.atguigu.config.MyTypeFilter
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/controller/BookController.class]
com.atguigu.controller.BookController
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/dao/BookDAO.class]
com.atguigu.dao.BookDAO
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/service/BookService.class]
com.atguigu.service.BookService
file [/Users/human/Desktop/Project/05SpringMVC/spring-annotation/target/classes/com/atguigu/test/MainTest.class]
com.atguigu.test.MainTest
测试类打印过滤结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService
6、@Controller
将类配置为Controller类
7、@Service
将类配置为service类
8、@Repository
将类配置为dao操作的类
9、@Component
将类配置为通用类组件
10、@Scope
调整bean的作用域范围,默认单实例,可以修改为多实例
Bean是默认单实例的,通过指明prototype(多实例)和singleton(单实例)属性指明是否单实例
- prototype:多实例
- singleton:单实例
- request:同一次请求创建一个实例
- session:同一个session创建一个实例
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {//Bean是默认单实例的,通过指明prototype(多实例)和singleton(单实例)属性指明是是否单实例//prototype:多实例//singleton:单实例//request:同一次请求创建一个实例//session:同一个session创建一个实例@Scope("prototype")@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}
}
测试
@Testpublic void testbeans() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);Object bean1 = applicationContext.getBean("person");Object bean2 = applicationContext.getBean("person");System.out.println(bean1==bean2);}
测试结果为false
11、@Lazy懒加载
实例默认在容器创建时立即加载
使用@Lazy后,当需要创建实例时才被加载
- 不使用懒加载
实体类构造函数
public Person(String name, Integer age) {System.out.println("给容器添加Person对象");this.name = name;this.age = age;}
测试代码
@Testpublic void testbeans() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);System.out.println("容器已创建完成");//没有获取类的代码,单实际上类的实例已经被加载进容器了}
测试结果
给容器添加Person对象
容器已创建完成
- 使用懒加载
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}
}
测试代码
@Testpublic void testbeans() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);System.out.println("容器已创建完成");Object bean1 = applicationContext.getBean("person");//这一句出现后才加载Person类}
测试结果
给容器添加Person对象
容器已创建完成
12、@Conditional
- 按一定条件注册bean,满足条件就给容器注册bean,否则不注入
- 要作为自定义条件,需要创建自定义condition类,并要实现Condition接口,并实现match方法
- conditional不仅可以标在方法上,还可以标记在类上
//判断是否是Linux系统的条件
//要作为自定义条件,要实现Condition接口,并实现match方法
//AnnotatedTypeMetadata:注释信息
public class LinuxCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {//判断linux洗洗ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();//获取类加载器ClassLoader classLoader = conditionContext.getClassLoader();//获得当前环境信息Environment environment = conditionContext.getEnvironment();//获取到bean定义的注册类BeanDefinitionRegistry registry = conditionContext.getRegistry();String OSproperty = environment.getProperty("os.name");if (OSproperty.contains("Mac OS X")){return true;}return false;}
}
另一个自定义条件
public class WindowsCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {Environment environment = conditionContext.getEnvironment();//获取操作系统信息String OSproperty = environment.getProperty("os.name");if (OSproperty.contains("Window")){return true;}return false;}
}
配置类信息
@Configuration
@ComponentScan(value = "com.atguigu")
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}@Conditional({WindowsCondition.class})@Bean("male")public Person personMale(){return new Person("lisi",33);}@Conditional({LinuxCondition.class})@Bean("female")public Person personFemale(){return new Person("wanger",23);}
}
测试类信息
@Testpublic void testBeans() {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);//获取ioc容器的运行环境ConfigurableEnvironment environment=applicationContext.getEnvironment();//获取操作系统名称String property = environment.getProperty("os.name");System.out.println(property);String[] namesForType = applicationContext.getBeanNamesForType(Person.class);for (String name:namesForType) {System.out.println(name);}}
测试结果
Mac OS X
person
female
13、给IOC容器中注册组件的5种方法
- 包扫描+组件类上标注注解:(@Controller,@Service,@Repository,@Component)
- @Bean:导入第三方包的组件
- @Import:快速给容器导入一个组件
1)@Import(要导入到容器的组件),容器中就会自动注册这个逐渐,id默认是全类名
2)ImportSelector:返回需要导入的组件的全类名数组
4.使用ImportBeanDefinitionRegistrar
5.使用Spring提供的FactoryBean(工厂bean)注册组件
1)默认获得的是工厂bean调用getObject创建的对象
2)要获取工厂bean本身,需要给id前面加一个&标识
14、@Import 快速导入一个类
使用@Import快速为配置类导入一个bean类
可以同时导入多个bean类
需要再配置类上方书写
- 创建被导入的bean类
public class Color {
}
public class Red {
}
- 给配置类导入该类
@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class})//在这里进行快速地导入,可以是数组形式
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}@Conditional({WindowsCondition.class})@Bean("male")public Person personMale(){return new Person("lisi",33);}@Conditional({LinuxCondition.class})@Bean("female")public Person personFemale(){return new Person("wanger",23);}
}
测试类代码
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);@Testpublic void testImport(){printBeans(applicationContext);}private void printBeans(AnnotationConfigApplicationContext applicationContext){String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String name:beanDefinitionNames) {System.out.println(name);}}
测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
person
female
15、ImportSelector接口导入一个类
- ImportSelector:返回需要导入的组件的全类名数组
- 需要实现ImportSelector接口并改写selectImports方法
创建需要被导入的类
public class Blue {
}
public class Yellow {
}
创建自己的Import类
public class MyImportSelect implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {//返回值是要导入到容器中的组件全类名//annotationMetadata:注解信息return new String[]{"com.atguigu.bean.Blue", "com.atguigu.bean.Yellow"};}
}
在配置类中设置@Import导入的自定义类选择器
注意:@Import({Color.class, Red.class,MyImportSelect.class})
@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class})
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}@Conditional({WindowsCondition.class})@Bean("male")public Person personMale(){return new Person("lisi",33);}@Conditional({LinuxCondition.class})@Bean("female")public Person personFemale(){return new Person("wanger",23);}
}
测试代码
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);@Testpublic void testImport(){printBeans(applicationContext);}private void printBeans(AnnotationConfigApplicationContext applicationContext){String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String name:beanDefinitionNames) {System.out.println(name);}}
测试结果
Color,Red,Blue,Yellow都有了
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female
16、使用ImportBeanDefinitionRegistrar接口导入类
自定义导入的类定义,需要实现ImportBeanDefinitionRegistrar接口,并重写 registerBeanDefinitions方法
创建一个需要被注入的类
public class RainBow {
}
创建自定义的注册类信息类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {//annotationMetadata:当前类的注解信息//beanDefinitionRegistry:beanDefinition注册类//把所有需要添加到容器中的bean,调用beanDefinitionRegistry.registerBeanDefinition手动注册类@Overridepublic void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {boolean red = beanDefinitionRegistry.containsBeanDefinition("com.atguigu.bean.Red");//判断定义中是否有红色boolean blue = beanDefinitionRegistry.containsBeanDefinition("com.atguigu.bean.Blue");//判断定义中是否有蓝色if(red && blue){//指定bean名RootBeanDefinition rainbowDefinition = new RootBeanDefinition(RainBow.class);//注册了一个bean,并指定了一个类名(别名)beanDefinitionRegistry.registerBeanDefinition("rainbow", rainbowDefinition);}}
}
在配置类中进行配置
注意:@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})
@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}@Conditional({WindowsCondition.class})@Bean("male")public Person personMale(){return new Person("lisi",33);}@Conditional({LinuxCondition.class})@Bean("female")public Person personFemale(){return new Person("wanger",23);}
}
测试类
@Testpublic void testImport(){printBeans(applicationContext);}private void printBeans(AnnotationConfigApplicationContext applicationContext){String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String name:beanDefinitionNames) {System.out.println(name);}}
测试结果
显示了rainbow
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female
rainbow
17、使用FactoryBean接口导入类
创建自定义工厂类,实现FactoryBean接口,并改写一下方法
getObject() //返回工厂生产的类对象
getObjectType()//返回工厂生产的类类型
isSingleton() //返回单例
创建自定义工厂类
这里实现FactoryBean接口,实现三个方法,注意泛型中使用Color类
public class ColorFactory implements FactoryBean<Color> {//返回一个Color对象,这个对象会添加到容器中@Overridepublic Color getObject() throws Exception {System.out.println("color factory generate a instance");return new Color();}@Overridepublic Class<?> getObjectType() {return Color.class;}@Overridepublic boolean isSingleton() {//true:返回单例,在容器中保存一份//false:返回多份类实例,每次获取工厂bean都会创建一个新的对象return false;}
}
在配置类中定义这个类组件
注意:
@Bean
public ColorFactory colorFactoryBean(){
return new ColorFactory();
}
}
@Configuration
@ComponentScan(value = "com.atguigu")
@Import({Color.class, Red.class,MyImportSelect.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
// @Scope("prototype")@Lazy@Bean("person")//指定bean的自定义idpublic Person person(){return new Person("张三",20);}@Conditional({WindowsCondition.class})@Bean("male")public Person personMale(){return new Person("lisi",33);}@Conditional({LinuxCondition.class})@Bean("female")public Person personFemale(){return new Person("wanger",23);}@Beanpublic ColorFactory colorFactoryBean(){return new ColorFactory();}
}
测试类
public class MainTest {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);@Testpublic void testImport(){printBeans(applicationContext);//工厂bean获取的是调用的是getObject创建的对象(Color类)Object bean1 = applicationContext.getBean("colorFactoryBean");Object bean2 = applicationContext.getBean("colorFactoryBean");System.out.println(bean1);System.out.println(bean2.getClass());//class com.atguigu.bean.ColorSystem.out.println(bean1==bean2);}private void printBeans(AnnotationConfigApplicationContext applicationContext){String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();for (String name:beanDefinitionNames) {System.out.println(name);}}
测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDAO
bookService
com.atguigu.bean.Color
com.atguigu.bean.Red
com.atguigu.bean.Blue
com.atguigu.bean.Yellow
person
female
colorFactoryBean
rainbow
color factory generate a instance
color factory generate a instance
com.atguigu.bean.Color@79c97cb
class com.atguigu.bean.Color
false