本文共 6848 字,大约阅读时间需要 22 分钟。
在将Spring框架应用于项目开发中时,繁多的xml配置文件会使项目的维护升级变得困难,特别是项目很大时,有时候会花掉大量的时间去定位相应的组件配置。为了解决这个问题,引入Spring框架中的强大注解变得很重要,同时,注解的学习更是为后期学习Spring Boot做好了铺垫。
@Configuration注解用于定义配置类,并用于构建bean定义,初始化Spring容器,被标注的类类似于Spring的xml配置文件中的beans标签。
给容器注册一个Bean;类型为方法返回值类型,id不指定时默认使用方法名作为id。
配置自动扫描相应的包。会自动扫描包路径下面的所有标注了@Controller、@Service、@Repository、@Component 的类。包含的属性如下:
如果是JDK8以上可以声明多个@ComponentScan进行配置,也可以在@ComponentScans中配置多个@ComponentScan。
//配置类==配置文件@Configuration //告诉spring这是一个配置文件@ComponentScan(value="com.jt",/*excludeFilters*/ includeFilters = { @Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})},useDefaultFilters=false)//配置自动扫描相应的包/*@ComponentScans(value = { @ComponentScan(value="com.jt",excludeFilters = { @Filter(type=FilterType.ANNOTATION,classes={Controller.class,Service.class})})})*//**@ComponentScan vaue:指定要扫描的包 *excludeFilters = Filter[],指定扫描的时候按照什么规则排除哪些组件。 *includeFilters = Filter[],指定扫描的时候只包含哪些组件。生效的前提是让useDefaultFilters *FilterType.ANNOTATION 按照注解 *FilterType.ASSIGNABLE_TYPE 按照给定的类型 *FilterType.ASPECTJ 使用ASPECTJ表达式 *FilterType.REGEX 使用正则表达式 *FilterType.CUSTOM 使用自定义规则(需要实现TypeFilter接口) * */public class MainConfig { //给容器注册一个Bean;类型为返回值类型,id不指定时默认使用方法名作为id @Bean("person1") public Person person(){ return new Person("lishi",20); }}
控制Bean的作用范围。
懒加载。
/**默认是单实例的 * prototype:多实例:ioc容器启动时并不会去调用方法创建对象, * 而是每次获取的时候才调用方法去创建对象。 * singleton:单实例(默认值):ioc容器启动时会调用方法创建对象并放入容器中。 * 以后每次获取是直接从容器(map.get())中获取。 * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * * 懒加载:对于单实例的Bean,默认容器启动的时候创建对象; * 懒加载就是容器启动的时候不创建对象,而是第一次获取(map.get())对象时才初始化对象。 * */ @Scope("prototype") @Lazy @Bean("person") public Person person(){ System.out.println("获取Person...."); return new Person("张三",25); }
标注在方法上时,按照一定的条件进行动态转配,满足条件才给容器中注册Bean。标注在配置类上时,满足当前条件,这个类配置中的所有Bean才能生效。其中这个条件类必须实现Condition接口。
/** * @Conditional({Condition}):按照一定的条件进行动态转配,满足条件才给容器中注册Bean * * 如果系统是Windows,给容器中注册bill * 如果系统是Linux,给容器中注册Linus * * */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person01(){ return new Person("Bill Gates",60); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person02(){ return new Person("linus",40); }
//判断对象是否是linuxpublic class LinuxCondition implements Condition{ /** * ConditionContext:判断条件能使用的上下文(环境) * AnnotatedTypeMetadata:标注了@Conditional的注释信息 * */ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //判断是否Linux系统 //常用方法 //1、能获得IOC使用的BeanFactory ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); //2、能获取到类加载器 ClassLoader classLoader = context.getClassLoader(); //3、获取当前环境信息 Environment environment = context.getEnvironment(); //4、获取到Bean定义的注册类 BeanDefinitionRegistry registry = context.getRegistry(); //判断容器中Bean的注册情况,也可以给容器注册Bean boolean difinition = registry.containsBeanDefinition("person"); String property = environment.getProperty("os.name"); if(property.contains("linux")){ return true; } return false; }}
//判断系统是否是windowspublic class WindowsCondition implements Condition{ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 判断是否Windows Environment environment = context.getEnvironment(); String property = environment.getProperty("os.name"); if(property.contains("Windows")){ return true; } return false; }}
快速给容器中注册组件。id默认是全类名。
@Import({Color.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 { //...}
@Import({MyImportSelector.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 { //.....}
//自定义逻辑返回需要导入的组件public class MyImportSelector implements ImportSelector{ //返回值就是要注册到容器中的组件 //AnnotationMetadata:当前标注@Import注解的类的所有注解信息 public String[] selectImports(AnnotationMetadata importingClassMetadata) { // TODO Auto-generated method stub //可以返回空数组,但是不能是null,否则会包空指针异常。 return new String[]{ "com.jt.bean.Color","com.jt.bean.Red"}; }}
@Import({MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})//@Import导入组件,id默认是组件的全类名public class MainConfig2 { //...}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * AnnotationMetadata:当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类; * 把所有需要添加到容器中的Bean,调用 * BeanDefinitionRegistry.registerBeanDefinition手工注册进容器 * */ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //定义注册Bean的条件 boolean difinition = registry.containsBeanDefinition("com.jt.bean.Red"); if(difinition){ //指定Bean的定义信息(Bean的类型,Bean的作用域...) RootBeanDefinition paramBeanDefinition = new RootBeanDefinition(RainBow.class); //注册一个bean,指定bean的别名 registry.registerBeanDefinition("com.jt.bean.RainBow", paramBeanDefinition); } }}
Spring提供了一个org.Springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。
@Beanpublic ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean();}
//创建一个Spring定义的FactoryBeanpublic class ColorFactoryBean implements FactoryBean{ //返回一个Color对象,这个对象会注册到容器中public Color getObject() throws Exception { // TODO Auto-generated method stub System.out.println("ColorFactoryBean...getObject()..."); return new Color();}public Class getObjectType() { // TODO Auto-generated method stub return Color.class;}//是否单实例//true:这个bean是单实例,在容器中保存一份//false:多实例,每次获取都会创建一个新的beanpublic boolean isSingleton() { // TODO Auto-generated method stub return true;}}
@Testpublic void testImport(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class); printBeans(applicationContext); //工厂Bean获取到的是调用getObject()创建的对象 Object object = applicationContext.getBean("colorFactoryBean"); Object object2 = applicationContext.getBean("colorFactoryBean"); System.out.println(object); System.out.println(object == object2); //获取colorFactoryBean本身时添加一个&符号 Object object3 = applicationContext.getBean("&colorFactoryBean"); System.out.println(object3);}
转载地址:http://kbkni.baihongyu.com/