Spring 注解版(1)

本文详细介绍Spring框架中组件的多种注册方式,包括通过配置类、注解、ImportSelector及ImportBeanDefinitionRegistrar等方法实现bean的注册。同时,探讨了不同作用域下bean的行为差异,以及如何使用条件注解Conditional实现bean的有条件注册。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.初步使用

(1).javaBean person

package com.atguigu.bean;
public class person {
private String name;
private Integer age;
public person() {
 super();
}
public person(String name, Integer age) {
 super();
 this.name = name;
 this.age = age;
}
public String getName() {
 return name;
}
public void setName(String name) {
 this.name = name;
}
public Integer getAge() {
 return age;
}
public void setAge(Integer age) {
 this.age = age;
}
@Override
public String toString() {
 return "person [name=" + name + ", age=" + age + "]";
}
}

(2).配置类MainConfig(相当于spring的xml文件)

package com.atguigu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.atguigu.bean.person;
@Configuration
public class MainConfig {
//给容器中注册一个Bean,类型为返回值的类型,id是默认用方法名作为id
 @Bean
public person person() {
 return new person("Linux",20);
} 
//此时id为ayst
 @Bean("ayst")
 public person person1() {
  return new person("ayst",25);
 } 
}

(3).测试类

package com.atguigu.text;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.bean.person;
import com.atguigu.config.MainConfig;
public class text1 {
public static void main(String[] args) {
 ApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfig.class);
 person person=(person)applicationContext.getBean("person");
    //打印person
 System.out.println(person);
    //遍历applicationContext中person 类bean的id
               String[] personNames=applicationContext.getBeanNamesForType(person.getClass());
               for(String p:personNames) {
                System.out.println(p);
               }
}
}

结果

十一月 15, 2019 1:03:28 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6e2c634b: startup date [Fri Nov 15 13:03:28 CST 2019]; root of context hierarchy
person [name=Linux, age=20]
person
ayst

pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.atguigu</groupId>
  <artifactId>spring-annotation</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
  </dependencies>
</project>

二.@ComponentScan(写在配置类上)

(1).excludeFilters:排除

@ComponentScan(value="com.atguigu",excludeFilters= {
//  type   :按照什么排除
//  eg:排除Controller注解
//  @Filter(type=FilterType.ANNOTATION,classes=Controller.class)
//  排除Controller和Service注解
  @Filter(type=FilterType.ANNOTATION,classes= {Controller.class,Service.class})
})

(2).includeFilters:只包含

//useDefaultFilters=false:禁用默认的扫描规则
@ComponentScan(value="com.atguigu",includeFilters={
@Filter(type=FilterType.ANNOTATION,classes=Controller.class)
},useDefaultFilters=false)

(3).@Filter type详解
①.FilterType.ANNOTATION:按照注解排除
eg:排除Controller注解

@ComponentScan(value="com.atguigu",excludeFilters= {
  @Filter(type=FilterType.ANNOTATION,classes=Controller.class)
  })

②.FilterType.ASSIGNABLE_TYPE:按照给定的类型
eg:只包含Controller注解和BookService类型的

@ComponentScan(value="com.atguigu",includeFilters={
@Filter(type=FilterType.ANNOTATION,classes=Controller.class)
  ,@Filter(type=FilterType.ASSIGNABLE_TYPE,classes=BookService.class)
  },useDefaultFilters=false)

③.FilterType.ASPECTJ:使用ASPECTJ表达式
④.FilterType.REGEX:使用正则指定
⑤.FilterType.CUSTOM:使用自定义规则
第一步:创建TypeFilter

package com.atguigu.config;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
public class MyTypeFilter implements TypeFilter {
/**
 * MetadataReader       :读取当前正在扫描类的信息
 * MetadataReaderFactory:可以获取到其他任何类信息的
 */
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
  // TODO Auto-generated method stub
//  获取当前类注解的信息
  AnnotationMetadata annotationMetadata=metadataReader.getAnnotationMetadata();
//  获取当前正在扫描的类信息
    ClassMetadata classMetadata =metadataReader.getClassMetadata();
//    获取当前类资源(类的全类名)
Resource rosource=metadataReader.getResource();
    String className=classMetadata.getClassName();
    System.out.println("--->"+className);
    //如果全类名中包含er,则加载进ioc容器中
    if(className.contains("er")) {
     return true;
    }
     return false;
     }
     }

第二步,使用自定义注解
eg:只包含全类名带er

@ComponentScan(value="com.atguigu",includeFilters={
@Filter(type=FilterType.CUSTOM,classes= {MyTypeFilter.class})
},useDefaultFilters=false)

三.Scope

(1).prototype:多实例,每次获取都会调用配置类中对应的方法创建对象(不会把创建的对象放进ioc容器中)
(2). singleton:单实例(默认值)ioc容器启动会调用方法创建对象放到ioc容器中,以后每次获取就是直接从ioc容器中拿
懒加载(针对singleton)
@Lazy:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化

(3).request:同一请求创建一个实例
(4).session:同一个session创建一个实例
使用
配置类中

@Scope("prototype")
@Bean("person2")
public person person2() {
  System.out.println("创建person对象");
 return new person("张三",25);
}

四.Conditional注解:按照条件注册bean

@Target({ElementType.TYPE, ElementType.METHOD}):可以注册在方法上,可以注册在配置类上
(1).注册在方法上:满足条件,该bean注册才会生效
eg:如果是Linux操作系统,则在ioc容器创建的时候加载进ioc容器中
第一步 创建Condition:判断条件

package com.atguigu.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class LinuxCondition implements Condition{
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;
 }
}

第二步:使用注解
配置类中

@Conditional(LinuxCondition.class)
@Bean("linux")
public person person03() {
 return new person("linux",48);
}

(2).注册在配置类上:满足当前条件,这个类中配置的所有bean注册才能生效
补充
Conditiona详解

public class windowsCondition implements Condition{
/**
 *ConditionContext:判断条件能使用的上下文
 *AnnotatedTypeMetadata:注释信息 
 */
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//  1.能获取ioc使用的beanfactory
  ConfigurableBeanFactory beanFactory=context.getBeanFactory();
//  2.获取类加载器
  ClassLoader classLoader=context.getClassLoader(); 
 //  3.获取当前环境信息
     Environment environment=context.getEnvironment()
 //  4.获取bean定义的注册类
     BeanDefinitionRegistry registry=context.getRegistry();
     //判断容器中是否含有person
     boolean definition=registry.containsBeanDefinition("person");
  // 5.T操作系统是否是windows系统
 String property=environment.getProperty("os.name");
   if(property.contains("Windows")) {
        return true;
       }
       return false;      
}
}  

五.组件注册
(1).包扫描+组件注册(@Component,@Repository,@Service,@Controller)
(2).配置类中@Bean
(3).@Import【快速给容器中导入一个组件】
①.@Import(要导入容器中的组件);
eg:导入color

@Import(color.class)

eg导入color,red

@Import({color.class,red.class})

②.ImportSelector:返回需要导入的组件全类名数组
eg:给Ioc容器中注入color,red以及用ImportSelector注入blue,black
第一步:创建ImportSelector

package com.atguigu.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
//自定义逻辑,返回需要导入的组件
public class MyImportSelector implements ImportSelector {
//返回值就是要导入到容器中组件的全类名
// AnnotationMetadata:当前标注@Import注解类的所有注解信息
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  // TODO Auto-generated method stub
   return new String[] {"com.atguigu.bean.blue","com.atguigu.bean.black"};
 }
 }

第二步:将ImportSelector加入@Import注解中

@Import({color.class,red.class,MyImportSelector.class})
public class MainConfig2 {}

③.ImportBeanDefinitionRegistrar:手动注册bean到容器中
eg:如果com.atguigu.bean.red和com.atguigu.bean.blue都注册进ioc容器,
则将RainBow注册进ioc容器,并指定注册bean名为rainBow
第一步:创建ImportBeanDefinitionRegistrar

package com.atguigu.condition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import com.atguigu.bean.RainBow;
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
 * AnnotationMetadata:当前类的注解信息
 * BeanDefinitionRegistry:BeanDefinition注册类;
 * 把所有需要添加到容器中的bean:
 * BeanDefinitionRegistry对象的registerBeanDefinition方法,手工注册进来
 */
 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  // TODO Auto-generated method stub
boolean definition=registry.containsBeanDefinition("com.atguigu.bean.red");
boolean definition2=registry.containsBeanDefinition("com.atguigu.bean.blue");
if(definition&&definition2) {
// 指定Bean定义信息;(Bean的类型,Bean。。。)
RootBeanDefinition beanDefinition=new RootBeanDefinition(RainBow.class);
 //注册一个Bean,指定bean名
 registry.registerBeanDefinition("rainBow", beanDefinition);
 }
 }
 }

第二步将ImportBeanDefinitionRegistrar加入@Import注解中

@Configuration
@Import({color.class,red.class,MyImportBeanDefinitionRegistrar.class,MyImportSelector.class})
public class MainConfig2 {}

④.使用spring提供的FactoryBean(工厂Bean)

  • 默认获取到的是工厂bean调用getObject创建的对象
  • 要获取工厂Bean本身,我们需要给id前面加一个&
    eg:&colorFactoryBean
  • 使用
    第一步:创建FactoryBean
package com.atguigu.bean;
import org.springframework.beans.factory.FactoryBean;
public class ColorFactoryBean implements FactoryBean<color>{
//返回一个color对象,这个对象会添加到容器中
public color getObject() throws Exception {
  // TODO Auto-generated method stub
  System.out.println("getObject()...");
  return new color();
 }
 //对象类型
 public Class<?> getObjectType() {
  return color.class;
 }
 //是否单例
// true:是:第一次获取时调用getObject()方法获取bean,在容器中保存一份
// false:否:每次获取都会调用getObject()方法获取一个新的bean
public boolean isSingleton() {
  return true;
 }
}

第二步:将FactoryBean注册进ioc容器
配置类中

@Bean
public ColorFactoryBean colorFactoryBean() {
 return new ColorFactoryBean();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值