spring bean注入

1、使用配置注入对象

向beans.xml注入bean:

<bean id="person" class="com.enjoy.cap1.Person">
	<property name="name" value="james"></property>
	<property name="age" value="19"></property>
</bean>

获取bean

//把beans.xml的类加载到容器
ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
//从容器中获取bean
Person person = (Person) app.getBean("person");

2、使用配置类注入对象

@Configuration
public class MainConfig {
	//给容器中注册一个bean, 类型为返回值的类型, 
	@Bean("abcPerson")
	public Person person01(){
		return new Person("james",20);
	}
}

获取bean

//把配置类中的bean加载到容器
ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class);
//从容器中获取bean,只用@Bean 则 bean ID 默认取方法名,即person01
Person person = (Person) app.getBean("abcPerson");

3、使用注解注入对象

3.1配置类添加扫面包注解,将指定包中的类加载到容器

@Configuration
@ComponentScan(value="com.enjoy.cap2")
public class Cap2MainConfig {
	//给容器中注册一个bean, 类型为返回值的类型, 
	@Bean
	public Person person01(){
		return new Person("james",20);
	}
}

添加注解

@Controller
public class OrderController { }

@Service
public class OrderService { }

@Repository
public class OrderDao{ }	

获取bean

//把配置类中的bean加载到容器
ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
//Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
String[] beanDefinitionNames = app.getBeanDefinitionNames();

3.2配置类添加扫描包注解,将指定包中的类加载到容器

@Configuration
@ComponentScan(value="com.enjoy.cap2")
public class Cap2MainConfig {
	//给容器中注册一个bean, 类型为返回值的类型, 
	@Bean
	public Person person01(){
		return new Person("james",20);
	}
}

添加注解

@Controller
public class OrderController { }

@Service
public class OrderService { }

@Repository
public class OrderDao{ }	

获取bean

//把配置类中的bean加载到容器
ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
//Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
String[] beanDefinitionNames = app.getBeanDefinitionNames();

3.2.1定制包扫描时的过滤规则

//@ComponentScan value:指定要扫描的包
//excludeFilters = Filter[] 指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] 指定扫描的时候只需要包含哪些组件
//useDefaultFilters = false 默认是true,扫描所有组件,includeFilters 要改成false,excludeFilters则是true
//----扫描规则如下
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;比如按BookService类型
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则,自已写类,实现TypeFilter接口

@Configuration
@ComponentScan(value = "com.enjoy.cap2", includeFilters = {
    @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
    @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderService.class})
}, useDefaultFilters = false)
public class Cap2MainConfig { }

@Configuration
@ComponentScan(value="com.enjoy.cap2",excludeFilters={
        @Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {OrderService.class})
})
public class Cap2MainConfig { }

添加注解

@Controller
public class OrderController { }

@Service
public class OrderService { }

@Repository
public class OrderDao{ }	

获取bean

//把配置类中的bean加载到容器
ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
//Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
String[] beanDefinitionNames = app.getBeanDefinitionNames();

FilterType.CUSTOM的例子

public class JamesTypeFilter implements TypeFilter {
    private ClassMetadata classMetadata;

    /*
     * MetadataReader:读取到当前正在扫描类的信息
     * MetadataReaderFactory:可以获取到其他任何类信息
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描的类信息
        classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("----->" + className);
        if (className.contains("Order")) {//当类包含er字符, 则匹配成功,返回true
            return true;
        }
        return false;
    }
}

@Configuration
@ComponentScan(value="com.enjoy.cap2",includeFilters={
        @Filter(type=FilterType.CUSTOM,classes={JamesTypeFilter.class})
},useDefaultFilters=false)
public class Cap2MainConfig { }

添加注解

@Controller
public class OrderController { }

@Service
public class OrderService { }

@Repository
public class OrderDao{ }	

获取bean

//把配置类中的bean加载到容器
ApplicationContext app = new AnnotationConfigApplicationContext(Cap2MainConfig.class);
//Spring 容器中所有 JavaBean 的名称,注解不指定bean ID 则默认取类名,且首字母小写
String[] beanDefinitionNames = app.getBeanDefinitionNames();

4、单例多例

@Configuration
public class Cap3MainConfig {
	//给容器中注册一个bean, 类型为返回值的类型, 默认是单实例
	@Bean
	public Student student(){
		return new Student("jack",20);
	}
	
	/*
	 * prototype:多实例: IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象
	 * singleton:单实例(默认):IOC容器启动的时候会调用方法创建对象并放到IOC容器中,以后每次获取的就是直接从容器中拿(大Map.get)的同一个bean
	 * request: 主要针对web应用, 递交一次请求创建一个实例
	 * session:同一个session创建一个实例
	 */
	@Scope("prototype")
	@Bean
	public Person person(){
		return new Person("james",20);
	}
}

验证

	AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap3MainConfig.class);
	//从容器中分别取两次person实例, 看是否为同一个bean
	Object bean1 = app.getBean("person");
	Object bean2 = app.getBean("person");
	System.out.println(bean1 == bean2);
	//从容器中分别取两次student实例, 看是否为同一个bean
	Object student1 = app.getBean("student");
	Object student2 = app.getBean("student");
	System.out.println(student1 == student2);

延迟加载

@Configuration
public class Cap4MainConfig {
	/*
	 * 懒加载: 主要针对单实例bean:默认在容器启动的时候创建对象
	 * 懒加载:容器启动时候不创建对象, 仅当第一次使用(获取)bean的时候才创建被初始化
	 */
	@Lazy
	@Bean
	public Person person(){
		System.out.println("给容器中添加person.......");
		return new Person("james",20);
	}
}

验证

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap4MainConfig.class);
System.out.println("IOC容器创建完成........");
app.getBean("person");//执行获取的时候才创建并初始化bean

5、@Conditional条件注册bean

@Configuration
public class Cap5MainConfig {
	@Bean("person")
	public Person person(){
		System.out.println("给容器中添加person.......");
		return new Person("person",20);
	}
	
	@Conditional(WinCondition.class)
	@Bean("lison")
	public Person lison(){
		System.out.println("给容器中添加lison.......");
		return new Person("Lison",58);
	}
	
	@Conditional(LinCondition.class)
	@Bean("james")
	public Person james(){
		System.out.println("给容器中添加james.......");
		return new Person("james",20);
	}
}

public class WinCondition implements Condition{
	/**
	 *
	 * @param context ConditionContext: 判断条件可以使用的上下文(环境)
	 * @param metadata AnnotatedTypeMetadata: 注解的信息
	 * @return
	 */
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO 是否为WINDOW系统
		//能获取到IOC容器正在使用的beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
		Environment environment = context.getEnvironment();
		String osName = environment.getProperty("os.name");
		if(osName.contains("Windows")){
			return true;
		}
		return false;
	}
}

public class LinCondition implements Condition{
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO 是否为WINDOW系统
		//能获取到IOC容器正在使用的beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		//获取当前环境变量(包括我们操作系统是WIN还是LINUX??)
		Environment environment = context.getEnvironment();
		String osName = environment.getProperty("os.name");
		if(osName.contains("linux")){
			return true;
		}
		return false;
	}
}

验证

//通过打印语句判断配置是否生效
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap5MainConfig.class);
System.out.println("IOC容器创建完成........");

6、@Import注册bean

@Configuration
@Import(value = { Dog.class,Cat.class, JamesImportSelector.class,JamesImportBeanDefinitionRegistrar.class })
public class Cap6MainConfig {
	/*
	 * 给容器中注册组件的方式
	 * 1,@Bean: [导入第三方的类或包的组件],比如Person为第三方的类, 需要在我们的IOC容器中使用
	 * 2,包扫描+组件的标注注解(@ComponentScan:  @Controller, @Service  @Reponsitory  @ Componet),一般是针对 我们自己写的类,使用这个
	 * 3,@Import:[快速给容器导入一个组件] 注意:@Bean有点简单
	 *      a,@Import(要导入到容器中的组件):容器会自动注册这个组件,bean 的 id为全类名
	 *      b,ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
	 *      c,ImportBeanDefinitionRegistrar:可以手动添加组件到IOC容器, 所有Bean的注册可以使用BeanDifinitionRegistry
	 *          写JamesImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口即可
	 *  4,使用Spring提供的FactoryBean(工厂bean)进行注册
	 *     
	 *   
	 */
	//容器启动时初始化person的bean实例
	@Bean("person")
	public Person person(){
		return new Person("james",20);
	}
	@Bean
	//@Scope("prototype") 加上则为多例,默认为单例
	public JamesFactoryBean jamesFactoryBean(){
		return new JamesFactoryBean();
	}
}
	
public class JamesImportSelector implements ImportSelector{
	public String[] selectImports(AnnotationMetadata importingClassMetadata){
		//返回全类名的bean
		return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"};
	}
}
	
public class JamesImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	/*
	 *AnnotationMetadata:当前类的注解信息
	 *BeanDefinitionRegistry:BeanDefinition注册类
	 *    把所有需要添加到容器中的bean加入;
	 */
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean bean1 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Dog");
		boolean bean2 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Cat");
		//如果Dog和Cat同时存在于我们IOC容器中,那么创建Pig类, 加入到容器
		//对于我们要注册的bean, 给bean进行封装,
		if(bean1 && bean2){
			RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);
			registry.registerBeanDefinition("pig", beanDefinition);
		}
	}
}

public class JamesFactoryBean implements FactoryBean<Monkey>{

	public Monkey getObject() throws Exception {
		return new Monkey();
	}

	public Class<?> getObjectType() {
		return Monkey.class;
	}
	
	public boolean isSingleton() {
		return true;
	}
}

验证

//通过打印语句判断配置是否生效
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
System.out.println("IOC容器创建完成........");
Object bean1 = app.getBean("jamesFactoryBean");
Object bean2 = app.getBean("jamesFactoryBean");//取Money
System.out.println("bean的类型="+bean1.getClass());
System.out.println(bean1 == bean2);
Object bean3 = app.getBean("&jamesFactoryBean");//取JamesFactoryBean
String[] beanDefinitionNames = app.getBeanDefinitionNames();
for(String name:beanDefinitionNames){
	System.out.println(name);
}

7、bean的生命周期

bean的生命周期:指   bean创建-----初始化----销毁  的过程
bean的生命周期是由容器进行管理的
我们可以自定义 bean初始化和销毁 方法: 容器在bean进行到当前生命周期的时候, 来调用自定义的初始化和销毁方法
单实例: 当容器关闭的时候,会调用destroy消耗
多实例: 容器只负责初始化,但不会管理bean, 容器关闭不会调用销毁方法
如何定义和销毁(3种方式):

7.1.1、指定初始化和销毁方法,可以在beanx.xml, 指定init-method和destory-mothod或者注解@Bean添加initMethod, destroyMethod

@Configuration
public class Cap7MainConfigOfLifeCycle {
	@Bean(initMethod="init", destroyMethod="destory")
	public Bike bike(){
		return new Bike();
	}
}

public class Bike {
	public Bike(){
		System.out.println("Bike constructor..............");
	}
	public void init(){
		System.out.println("Bike .....init.....");
	}
	public void destory(){
		System.out.println("Bike.....destory");
	}
}

验证

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap7MainConfigOfLifeCycle.class);
System.out.println("IOC容器创建完成........");
//容器关闭调用destory方法
app.close();

7.1.2、实现InitializingBean 和 DisposableBean接口

@ComponentScan("com.enjoy.cap7.bean")
@Configuration
public class Cap7MainConfigOfLifeCycle {
	@Bean(initMethod="init", destroyMethod="destory")
	public Bike bike(){
		return new Bike();
	}
}

@Component
public class Train implements InitializingBean, DisposableBean{
	public Train(){
		System.out.println("Train......constructor............");
	}
	//当我们bean销毁时,调用此方法
	public void destroy() throws Exception {
		System.out.println("Train......destory......");
	}
	//当我们的bean属性赋值和初始化完成时调用
	public void afterPropertiesSet() throws Exception {
		System.out.println("Train.......afterPropertiesSet()...");
	}
}

验证

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap7MainConfigOfLifeCycle.class);
System.out.println("IOC容器创建完成........");
//容器关闭调用destory方法
app.close();

在这里插入图片描述
7.1.3、使用JSR250规则定义的(java规范)两个注解来实现

@ComponentScan("com.enjoy.cap7.bean")
@Configuration
public class Cap7MainConfigOfLifeCycle {
	@Bean(initMethod="init", destroyMethod="destory")
	public Bike bike(){
		return new Bike();
	}
}

@Component
public class Jeep {
	public Jeep(){
		System.out.println("Jeep.....constructor........");
	}
	@PostConstruct
	public void init(){
		System.out.println("Jeep.....@PostConstruct........");
	}
	@PreDestroy
	public void destory(){
		System.out.println("Jeep.....@PreDestroy......");
	}
}

验证

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap7MainConfigOfLifeCycle.class);
System.out.println("IOC容器创建完成........");
//容器关闭调用destory方法
app.close();

在这里插入图片描述
7.2、BeanPostProcessor类: bean的后 置处理器,在bean初始化之前调用进行拦截

@ComponentScan("com.enjoy.cap7.bean")
@Configuration
public class Cap7MainConfigOfLifeCycle {
	@Bean(initMethod="init", destroyMethod="destory")
	public Bike bike(){
		return new Bike();
	}
}

@Component
public class TestBeanPostProcessor implements BeanPostProcessor{
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		//返回一个的对象(传过来的对象)
		//在初始化方法调用之前进行后置处理工作,
		//什么时候调用它: init-method=init之前调用
		System.out.println("BeforeInitialization...."+beanName);
		return bean;
	}
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("AfterInitialization...."+beanName);
		return bean;
	}
}

验证

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap7MainConfigOfLifeCycle.class);
System.out.println("IOC容器创建完成........");

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值