spring注解开发-01

导包

	<dependencies>
			<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-context</artifactId>
				<version>4.3.13.RELEASE</version>
			</dependency>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>4.12</version>
			</dependency>
</dependencies>

传统的xml格式与注解开发的对比

首先准备一个Person类:

public class Person {
	
	private String name;
	
	private Integer age;

	//getter、setter、无参构造、有参构造、toString省略

}

xml格式

  • 第一步,首先需要准备一份xml配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <bean id="person" class="com.atguigu.pojo.Person">
      	<property name="name" value="zhangsan"></property>
      	<property name="age" value="22"></property>
      </bean>
    
  • 第二步,通过资源加载器去加载文件

      ApplicationContext context = new ClassPathXmlApplicationContext("my-context-beans.xml");
      Person person = (Person)context.getBean("person");
      System.out.println(person);
    

注解开发模式

  • 1、首先需要准备一份配置类:

      @Configration
      public class MyConfigration {
      
      	/**
      	 * @Bean 相当于bean标签,
      	 * 返回值类型是最后的返回类型,
      	 * 方法名是默认id
      	 * @Bean 将某个容器注入到IOC容器中
      	 * @return
      	 */
      	@Bean("person")
      	public Person person01 (){
      		return new Person("lisi" , 24);
      	}
      }
    
  • 2、通过注解加载器去加载:

      		//创建一个通过注解方式注入bean的对象
      		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfigration.class);
      		/*Person person = context.getBean(Person.class);
      		System.out.println("person = " + person);*/
      		String[] definitionNames = context.getBeanDefinitionNames();
      		for(String name : definitionNames){
      			System.out.println(name);
      		}
    

@ComponentScan

	/**
	 * @Configuration 相当于之前的xml文件,只是这里转换成了java配置
	 * @ComponentScan 配置包扫描,basePackages属性是配置要扫描的类
	 * excludeFilters配置的是排除要扫描的类的信息
	 * includeFilters配置的是需要扫描指定过滤类的信息,使用时需要关闭默认的过滤类型,useDefaultFilters = false
	 * 常用的过滤信息有四个,他们分别是
	 * FilterType.ANNOTATION:通过注解进行过滤,
	 * FilterType.ASSIGNABLE_TYPE,通过类型进行过滤
	 * FilterType.ASPECTJ:通过AspectJ的方式进行过滤
	 * FilterType.REGEX:通过正则表达式的方式进行过滤
	 * FilterType.CUSTOM:自定义过滤规则
	 * @ComponentScans 可以配置多个扫描器,每一个扫描器都是一个单独的@ComponentScan
	 *
	 */
	@Configuration
			/*@ComponentScan(basePackages = "com.atguigu" ,includeFilters = {
					@ComponentScan.Filter(type = FilterType.ANNOTATION , classes = {Controller.class , Service.class } )
			})*/
	
	@ComponentScan(basePackages = "com.atguigu",includeFilters = {
	
			@ComponentScan.Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class)
	},useDefaultFilters = false)
	public class MyConfigration {
	
		/**
		 * @Bean 相当于bean标签,
		 * 返回值类型是最后的返回类型,
		 * 方法名是默认id
		 * @Bean 将某个容器注入到IOC容器中
		 * @return
		 */
		@Bean("person")
		public Person person01 (){
			return new Person("lisi" , 24);
		}
}
/**
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class,Service.class}),通过注解的方式进行过滤
@ComponentScan.Filter(type = FilterType.CUSTOM , classes = MyTypeFilter.class),这是一个自定义过滤规则
*/

自定义过滤规则

public class MyTypeFilter implements TypeFilter {

    /**
     *
     * @param metadataReader 读取的是扫描的包中的注解,类,的信息
     * @param metadataReaderFactory 读取的是其他任何包中的注解,类,的信息
     * @return true代表是将对应的信息放置IOC容器,false是不放置在容器
     * @throws IOException
     */
    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);
        //若名称中包含的per,就加入到spring容器
        if(className.contains("per")){
            return true;
        }
        return false;
    }
}

@Scope作用域和@Lazy懒加载

@Scope作用域

singleton:当容器启动的时候,会将对象放入IOC容器,第二次直接去容器当中取,相当于map.get(),容器创建时会创建对象并加入IOC容器
prototype:每次都会得到一个全新的对象,不会放入IOC容器,容器创建时,不会创建对象,当获取对象时,才会创建对象
request:在同一个请求当中,对象是唯一的
session:在同一个会话中,对象是唯一的

懒加载

前提:必须保证Bean的Scope是单例的,容器启动时bean就会创建;
懒加载,就是容器启动时先不创建bean,当第一次调用对象的时候,将对象定义并初始化,并加入到IOC容器中;

@Conditional条件匹配

1、在@Configuration中注入一个@Bean

	   @Bean("Bill")
	    @Conditional({LinuxCondition.class})
	    public Person person01(){
	        return new Person("Bill Gates" , 62);
	    }

2、创建的条件匹配LinuxCondition对象的内容为:

public class LinuxCondition implements Condition {
    /**
     *
     * @param context ConditionContext 上下文对象
     * @param metadata AnnotatedTypeMetadata 当前带有注解的类
     * @return
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取环境信息对象
        Environment environment = context.getEnvironment();
        //获取系统信息
        String property = environment.getProperty("os.name");
        if(property.contains("linux")){
            return true;
        }
        return false;
    }
}

3、方法上加入的@Conditional({LinuxCondition.class}),只有满足条件才会加入到IOC容器中,也可以作用到类上,此类所有的Bean只有满足才会加入IOC;

Import导入的四种方式

  • Configuration对象的前缀

      @Configuration
      @Conditional({WindowsCondition.class})
      @Import({Color.class , MyImportSelector.class , MyImportBeanDefinitionRegistrar.class})
      public class MyConfigration2 
    

1、import导入

  • Color实体类:

      public class Color{}
    
  • 创建好实体类之后,可直接通过@Import导入即可,生成对象的id名为完整的包路径+类名

2、ImportSelector方式:

  • Blue实体类:

      public class Blue{}
    
  • Yellow实体类:

      public class Yellow{}
    
  • 自定义一个ImportSelector实现类,这里有一个例子:

      public class MyImportSelector implements ImportSelector {
          /**
           *
           * @param importingClassMetadata AnnotationMetadata 带有注解类信息
           * @return
           */
          public String[] selectImports(AnnotationMetadata importingClassMetadata) {
      		//这里返回的可以是空数组,但不能是null
              return new String[]{"com.atguigu.pojo.Blue" , "com.atguigu.pojo.Yellow"};
          }
      }
    
  • 创建好实体类之后,自定义一个ImportSelector实现类,并重写对应的方法,@Import导入即可,生成对象的id名为完整的包路径+类名

3、ImportBeanDefinitionRegistrar方式:

  • Red实体类:

      public class Red{}
    
  • 自定义一个ImportBeanDefinitionRegistrar 实现类,这里有一个例子:

      public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
      /**
       *
       * @param importingClassMetadata AnnotationMetadata带有注解的类的信息
       * @param registry BeanDefinitionRegistry:Bean对象注册器
       */
      public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
          //获取所有的Bean名称
          String[] beanDefinitionNames = registry.getBeanDefinitionNames();
          List<String> strings = Arrays.asList(beanDefinitionNames);
          if(strings.contains("com.atguigu.pojo.Color") && strings.contains("com.atguigu.pojo.Blue")) {
              //创建一个RootBeanDefinition对象
              RootBeanDefinition beanDefinition = new RootBeanDefinition(Red.class);
              registry.registerBeanDefinition("red", beanDefinition);
          }
      }
    
  • ImportBeanDefinitionRegistrar方式创建的bean,Bean的id是自己命名的

4、FactoryBean方式导入

/**
 * FactoryBean 是一个工厂bean的接口,需要一个实现类去实现FactoryBean接口
 * getObject 需要返回的对象
 * getObjectType 返回的对象类型
 * isSingleton 是否为单例,true为单例,false为多例
 */
@Component
public class ColorFactoryBean implements FactoryBean<Color> {
    public Color getObject() throws Exception {
        System.out.println("创建了Bean实例对象");
        return new Color();
    }

    public Class<?> getObjectType() {
        return Color.class;
    }

    public boolean isSingleton() {
        return false;
    }
}
  • 通过ComponentScan进行包扫描;

       		  ApplicationContext context = new AnnotationConfigApplicationContext(MyConfigration2.class);
       		  //带&返回的是colorFactoryBean对象,可以去BeanFactory类中取查对应的前缀"&"
              Object colorFactoryBean = context.getBean("&colorFactoryBean");
              System.out.println(colorFactoryBean.getClass());
              //不带&返回的是Color对象
              Object colorFactoryBean1 = context.getBean("colorFactoryBean");
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值