Spring注解开发

Posted -王二毛-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring注解开发相关的知识,希望对你有一定的参考价值。

一、注入组件方式一:使用@Configuration和@Bean

1.1、对照组:通过原始xml方式给容器注入组件


bean:Person

beans.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
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<bean id= "person" class="com.atguigu.bean.Person">
		<property name="age" value="18"></property>
		<property name="name" value="zhangsan"></property>
	</bean>
	
</beans>

测试类MainTest.java

public class MainTest 
	public static void main(String[] args) 
		//使用ClassPathXmlApplicationContext根据名称加载解析类路径下的beans.xml文件,返回bean容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		//从容器中,根据名称获取bean实例对象
		Person bean =(Person) applicationContext.getBean("person");
		System.out.println(bean);
	

结果

1.2、使用@Configuration和@Bean注解


配置类MainConfig.java

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id,此时方法名不再作为id
	public Person person01() 
		return new Person("ermao",20);
	

测试类MainTest.java

public class MainTest 
	public static void main(String[] args) 
		//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
		ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
		//从容器中,通过类型获取bean
		Person bean =(Person) applicationContext.getBean(Person.class);
		System.out.println(bean);

		//查看Person类型的组件在容器中的名字是什么
		String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
		for (String name : namesForType) 
			System.out.println(name);
		
	

1.3、@ComponentScan自动扫描组件和配置扫描规则

1.3.1、对照组:通过原始xml结合<context:component-scan>方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 包扫描、只要标注了@Controller、@Service、@Repository,@Component都会被扫描 -->
	<context:component-scan base-package="com.atguigu"></context:component-scan>
	<bean id= "person" class="com.atguigu.bean.Person">
		<property name="age" value="18"></property>
		<property name="name" value="zhangsan"></property>
	</bean>
	
</beans>

1.3.2、使用 @ComponentScan注解方式


MainConfig.java

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu")//配置包扫描
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id
	public Person person01() 
		return new Person("ermao",20);
	

测试

public class IOCTest 
	@Test
	public void test01() 
		//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext(MainConfig.class);
		//获取所有的bean,包括自定义和系统的所有bean
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : definitionNames) 
			System.out.println(name);
		
	
	

结果

1.3.3、通过对@ComponentScan注解设置参数配置扫描规则

1)、excludeFilters排除指定的,其他都扫描

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",excludeFilters = 
		@Filter(type = FilterType.ANNOTATION,classes = Controller.class,Service.class)
)//配置包扫描
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id
	public Person person01() 
		return new Person("ermao",20);
	

2)、includeFilters只扫描指定的组件,加到容器中

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",includeFilters = 
		@Filter(type = FilterType.ANNOTATION,classes = Controller.class,Service.class)
,useDefaultFilters = false)//配置包扫描
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id
	public Person person01() 
		return new Person("ermao",20);
	

3)、自定义Filter指定配置规则


自定义配置规则类和定义配置规则
MyTypeFilter.java

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;
		
		
		return false;
	


使用自定义的配置规则
MainConfig.java

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
@ComponentScan(value = "com.atguigu",includeFilters = 
		//根据注解配置
//		@Filter(type = FilterType.ANNOTATION,classes = Controller.class,Service.class),
		//根据类型配置
//		@Filter(type = FilterType.ASSIGNABLE_TYPE,classes = BookService.class),
		//自定义规则
		@Filter(type = FilterType.CUSTOM,classes = MyTypeFilter.class)
,useDefaultFilters = false)//配置包扫描
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id
	public Person person01() 
		return new Person("ermao",20,"二毛");
	


测试

@Test
	public void test01() 
		//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext(MainConfig.class);
		
		//获取所有的bean
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		for (String name : definitionNames) 
			System.out.println(name);
		
		
		//关闭容器		
		applicationContext.close();
	

二、注入组件方式二:使用@Import快速注入

2.1、直接快速导入


快速导入组件

测试

@Test
public void test01() 
	//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
	AnnotationConfigApplicationContext applicationContext = 
			new AnnotationConfigApplicationContext(MainConfig.class);
	
	//获取bean
	String[] namesForType = applicationContext.getBeanDefinitionNames();
	for (String name : namesForType) 
		System.out.println(name);
	
	
	//关闭容器		
	applicationContext.close();

结果

2.2、通过ImportSelector条件快速导入

将需要快速导入的组件放到一个ImportSelector类中,封装成数组返回

封装
MyImportSelector.java

//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector 

	//返回值,就是到导入到容器中的组件全类名
	//AnnotationMetadata:当前标注@Import注解的类的所有注解信息
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) 
		//importingClassMetadata
		//方法不要返回null值
		return new String[]"com.atguigu.bean.Blue","com.atguigu.bean.Yellow";
	


注册

测试

@Tescst
public void test01() 
	//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
	AnnotationConfigApplicationContext applicationContext = 
			new AnnotationConfigApplicationContext(MainConfig.class);
	
	//获取bean
	String[] namesForType = applicationContext.getBeanDefinitionNames();
	for (String name : namesForType) 
		System.out.println(name);
	
	
	//关闭容器		
	applicationContext.close();

2.3、通过ImportBeanDefinitionRegistrar:手动注册bean到容器中


MyImportBeanDefinitionRegistrar.java

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar 

	/**
	 * AnnotationMetadata:当前类的注解信息
	 * BeanDefinitionRegistry:BeanDefinition注册类;
	 * 		把所有需要添加到容器中的bean;调用
	 * 		BeanDefinitionRegistry.registerBeanDefinition手工注册进来
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 
		
		//判断是否有
		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);
		
	


三、注入组件方式三:使用FactoryBean注入


创建一个Spring定义的FactoryBean
ColorFactoryBean.java

public class ColorFactoryBean implements FactoryBean<Color> 
	//返回一个Color对象,这个对象会添加到容器中
	@Override
	public Color getObject() throws Exception 
		System.out.println("ColorFactoryBean...getObject...");
		return new Color();
	

	@Override
	public Class<?> getObjectType() 
		return Color.class;
	

	//是单例?
	//true:这个bean是单实例,在容器中保存一份
	//false:多实例,每次获取都会创建一个新的bean;
	@Override
	public boolean isSingleton() 
		return false;
	

注册
MainConfig.java

测试

@Test
	public void test01() 
		//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
		AnnotationConfigApplicationContext applicationContext = 
				new AnnotationConfigApplicationContext(MainConfig.class);
		
		//工厂Bean获取的是调用getObject创建的对象
		Object bean2 = applicationContext.getBean("colorFactoryBean");
		Object bean3 = applicationContext.getBean("colorFactoryBean");
		System.out.println("bean的类型:"+bean2.getClass());
		System.out.println(bean2 == bean3);
		
		Object bean4 = applicationContext.getBean("&colorFactoryBean");
		System.out.println(bean4.getClass());
		
		//关闭容器		
		applicationContext.close();
	

结果

四、@Scope设置组件作用域

4.1、对照组:相对于xml文件的scope属性

4.2、使用@Scope注解方式


设置
MainConfig.java

//创建配置,这个配置类等同于beans.xml
@Configuration	//告诉Spring这是一个配置类
/*
 * 默认是单实例
 * 
 * prototype:多实例的:多实例的: ioc容器启动并不会去调用方法创建对象放在容器中。
			每次获取的时候才会调用方法创建对象;
 * singleton:单实例的(默认值): ioc容器启动会调用方法创建对象放到io.c容器中。
            以后每次获取就是直接从容器中拿
 * request:同一次请求创建一个实例
 * session:同一个session创建一个实例
*/
@Scope("singleton")
public class MainConfig 
	//给容器添加一个bean,类型为返回值的类型,id默认是用方法名作为id
	@Bean("person")//指定id
	public Person person01() 
		return new Person("ermao",20,"二毛");
	

测试

@Test
public void test01() 
	//使用AnnotationConfigApplicationContext加载配置类,返回IOC容器
	//如果是单实例:初始化ioc容器启动会调用方法创建对象放到io.c容器中。以后每次获取就是直接从容器中拿
	AnnotationConfigApplicationContext applicationContext = 
			new AnnotationConfigApplicationContext(MainConfig.class);
	
	//通过类型获取bean
	Person bean1 =(Person) applicationContext.getBean("person");//多实例,每次获取的时候才会调用方法创建对象
	Person bean2 =(Person) applicationContext.getBean("person");
	System.out.println(bean1 == bean2);
	
	//关闭容器		
	applicationContext.close();

结果

五、@Lazy组件懒加载

基于spring注解AOP的异常处理

Spring+MyBatis纯注解零XML整合

Spring下面的@Transactional注解的讲解

Spring配置类理解(Lite模式和Full模式)

花了两天肝出来的Spring注解编程的发展历程,相信对每个小伙伴都会有帮助的,建议收藏哦。

花了两天肝出来的Spring注解编程的发展历程,相信对每个小伙伴都会有帮助的,建议收藏哦。