Spring注解驱动开发-组件注册(一)

关联文章:

Spring注解驱动开发-组件注册(一)

Spring注解驱动开发-生命周期(二)

Spring注解驱动开发-属性赋值&自动装配(三)

Spring注解驱动开发-AOP(四)

大纲图解

@Configuration和@Bean给容器中注册组件


使用xml注册




    
        
        
    
public class MainTest {
	public static void main(String[] args) {
                //通过ClassPathXmlApplicationContext获取配置文件
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
		Person person = (Person) ac.getBean("person");
		System.out.println(person);
	}
}

输出:Person(name=小红, age=18)

注解


//配置类==配置文件
@Configuration  //告诉Spring这是一个配置类
public class MainConfig {
	//给容器中注册一个Bean;类型为返回值类型,id默认是用方法名
	//也可以指定
	@Bean(value="person00")
	public Person person() {
		return new Person("小黑",18);
	}
}
public class MainTest {
	public static void main(String[] args) {
                //通过AnnotationConfigApplicationContext获取配置类
	        ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
		Person person = (Person) ac.getBean("person00");
		System.out.println(person);
		
		String[] namesForType = ac.getBeanNamesForType(Person.class);
		for (String string : namesForType) {
			System.out.println(string);
		}
	}
}

输入:Person(name=小黑, age=18)

           person00

@ComponentScan自动扫描组件&扫描规则


xml方式



注解


//配置类==配置文件
@Configuration  //告诉Spring这是一个配置类
@ComponentScan(value="com.zxc") //扫描注册
public class MainConfig {
	
}

添加controller,service

public class MainTest {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
		//获取IOC容器里的Bean名字
		String[] beanDefinitionNames = ac.getBeanDefinitionNames();
		for (String string : beanDefinitionNames) {
			System.out.println(string);
		}
	}
}

输出

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
employeeController
IEmployeeService

扫描规则:

public abstract Filter[] includeFilters(); 指定扫描的时候只需要包含哪些组件

public abstract Filter[] excludeFilters();指定扫描的时候按照什么规则排除那些组件

//配置类==配置文件
import org.springframework.context.annotation.FilterType;
@Configuration  //告诉Spring这是一个配置类
@ComponentScan(value="com.zxc",excludeFilters={
	@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})
}) //扫描注册
public class MainConfig {
	
}

测试是没有贴@Controller的Bean

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
IEmployeeService

自定义TypeFilter指定过滤规则:


 FilterType ANNOTATION;              按照注解
 FilterType ASSIGNABLE_TYPE;   按照给的类型
 FilterType ASPECTJ;                     使用ASPECTJ表达式
 FilterType REGEX;                         使用正则表达式
 FilterType CUSTOM;                      使用自定义规则

自定义规则的类:

public class MyTypeFilter implements 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;
		}
		//返回false,不匹配规则,反之匹配
		return false;
	}
}

注意:使用自定义注解记得需要关闭默认过滤器useDefaultFilters = false

@Configuration  //告诉Spring这是一个配置类
@ComponentScan(value="com.zxc",includeFilters={
		//扫描时按照自定义规则的类过滤
	@Filter(type=FilterType.CUSTOM,classes= {MyTypeFilter.class})
},useDefaultFilters = false) //扫描注册
public class MainConfig {
	
}

@Scope设置组件作用域


singleton:单例的(默认的);ioc容器启动时创建对象,以后从容器(map.get())中拿

prototype:多例的; ioc容器启动不会去调用方法创建对象放在容器,每次获取创建对象

request:同一个请求创建一个实例

session:同一个session创建一个实例

Spring注解驱动开发-组件注册(一)_第1张图片

@Lazy


懒加载:

单实例bean,默认在容器启动的时候创建对象

懒加载,容器启动不会创建对象。第一次使用Bean创建对象,并初始化

 

@Conditional ({condition})按照条件注册bean


需求:如果是windows,给容器注册Bill,

           如果是linux系统,给容器注册Tom

配置类:

@Configuration  //告诉Spring这是一个配置类
public class MainConfig {
	@Bean("小红")
	public Person person() {
		return new Person("小红",19);
	}
	//根据条件注册Bean
	@Conditional(WindowsCondition.class)
	@Bean("Bill")
	public Person person1() {
		return new Person("Bill",66);
	}
	
	@Conditional(Linux.class)
	@Bean("Tom")
	public Person person2() {
		return new Person("Tom",66);
	}
}

判断条件需要实现Condition接口:

//判断是否Windows系统
public class WindowsCondition implements Condition {
	/**
	 * conditionContext:判断条件能使用的上下文(环境)
         * annotatedTypeMetadata:注释信息
	 */
	@Override
	public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
                Environment environment = conditionContext.getEnvironment();
		// 获取操作系统的名称
		String osName = environment.getProperty("os.name");
		if (osName.contains("Windows")) {
			return true;
		}
		return false;
	}
}
//判断是否是Linux系统
public class Linux implements Condition{
	@Override
	public boolean matches(ConditionContext conditioncontext, AnnotatedTypeMetadata annotatedtypemetadata) {
		Environment environment = conditioncontext.getEnvironment();
		String osName = environment.getProperty("os.name");
		
		if(osName.contains("Linux")) {
			return true;
		}
		return false;
	}
}

ConditionContext类有以下方法:

// 1.获取IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
// 2.获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
// 3.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
// 4.获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
// 判断容器中bean注册情况,也可以给容器注册一个bean
boolean containsBeanDefinition = registry.containsBeanDefinition("小红");
public class MainTest {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
		// 获取环境信息
		Environment environment = ac.getEnvironment();
		String name = environment.getProperty("os.name");
		System.out.println(name);

		// 打印容器中注册的Bean名字
		String[] beanNamesForType = ac.getBeanNamesForType(Person.class);
		for (String string : beanNamesForType) {
			System.out.println(string);
		}
		// 获取容器bean
		Map person = ac.getBeansOfType(Person.class);
		System.out.println(person);
	}
}

输出:

Windows 10  //当前操作系统类型
小红           
Bill        //满足时windows操作系统的条件,被注册到IOC容器中
{小红=Person(name=小红, age=19), Bill=Person(name=Bill, age=66)}

补充:@Conditional 贴到类上,表示满足当前条件,这个类中所以Bean都可以注册

 

@Import -给容器快速导入一个组件


给容器注册组件:

  • 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]
  • @Bean[导入第三方包里的组件]
  • @Import[快速给容器导入一个组件]

1),@Import(要导入容器的组件);容器会自动注册这个组件,id默认时全类名

2),ImportSelector(接口):返回需要导入的组件全类名数组(用的最多)

3),ImportBeanDefinitionRegistrar,手动注册bean到容器中

4),使用Spring提供的FactoryBean(工厂Bean)

      1)默认获取到的是工厂bean调用getObject()创建的对象

      2)要获取工厂Bean本身,需要在id前面加一个&

           Object bean3 = ac.getBean("&colorFactoryBean");


需要注册的组件Blue,Red(类)

  • @Import直接导入
@Configuration  //告诉Spring这是一个配置类
@Import({Red.class,Blue.class})   //关注点
public class MainConfig {
	
}
  • ImportSelector接口-导入的选择器:

//自定义需要注册的Bean
public class MyImportSelector implements ImportSelector {
	/**
	 * 返回值就是需要导入容器中的组件全 类名
	 *  annotationmetadata:当前标注@Import注解类的所以注解信息
	 */
	@Override
	public String[] selectImports(AnnotationMetadata annotationmetadata) {
		// 不能返回null,不然空指针
		return new String[] { "com.zxc.bean.Black", "com.zxc.bean.Orange" };
	}
}

 配置类:

@Configuration  //告诉Spring这是一个配置类
@Import({Red.class,Blue.class,MyImportSelector.class})   //关注点
public class MainConfig {
	
}

测试:

public class MainTest {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
		String[] beanDefinitionNames = ac.getBeanDefinitionNames();
		for (String string : beanDefinitionNames) {
			System.out.println(string);
		}
	}
}

输出:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig             //配置类
com.zxc.bean.Red       //@Import 直接注册
com.zxc.bean.Blue      //@Import 直接注册
com.zxc.bean.Black     //实现ImportSelector接口返回需要注册的全类名方式
com.zxc.bean.Orange    //同上
  • ImportBeanDefinitionRegistrar接口- 手动注册

ImportBeanDefinitionRegistrar实现类:

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
	/**
	 * AnnotationMetadata: 当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类;
	 * 把所以需要注册的Bean,调用BeanDefinitionRegistry.registerBeanDefinition()方法手动注册
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata annotationmetadata,
			BeanDefinitionRegistry registry) {
		//容器中是否有id为com.zxc.bean.Red的Bean
		boolean definition = registry.containsBeanDefinition("com.zxc.bean.Red");
		boolean definition2 = registry.containsBeanDefinition("com.zxc.bean.Blue");
		if(definition && definition2) {
			//指定bean名
			RootBeanDefinition beandefinition = new RootBeanDefinition(RainBow.class);
			registry.registerBeanDefinition("rainBow", beandefinition);
		}
	}
}

配置类:

@Configuration  //告诉Spring这是一个配置类
@Import({Red.class,Blue.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MainConfig {
	
}

 结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.zxc.bean.Red
com.zxc.bean.Blue
com.zxc.bean.Black
com.zxc.bean.Orange
rainBow            //手动注册
  • 实现 FactoryBean接口

public class ColorFactoryBean implements FactoryBean {
	//生成bean对象
	@Override
	public Color getObject() throws Exception {
		return new Color();
	}
	//返回生成的Bean类型
	@Override
	public Class getObjectType() {
		return Color.class;
	}
	//是否是单例
	@Override
	public boolean isSingleton() {
		return true;
	}

}

配置类:

@Configuration  //告诉Spring这是一个配置类
public class MainConfig {
	@Bean
	public ColorFactoryBean colorFactoryBean() {
		return new ColorFactoryBean();
	}
}

测试:

public class MainTest {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
		Object bean = ac.getBean("colorFactoryBean");
		System.out.println("bean的类型-->"+bean.getClass());
		Object bean2 = ac.getBean("colorFactoryBean");
		System.out.println(bean==bean2);
		//获取工成本身
		Object bean3 = ac.getBean("&colorFactoryBean");
		System.out.println(bean3.getClass());
	}
}

输出:

bean的类型-->class com.zxc.bean.Color
true
class com.zxc.bean.ColorFactoryBean

 

你可能感兴趣的:(Spring)