Spring简介及应用-IOC

Spring是一个轻量级的IOC(控制反转)/DI(依赖注入)和AOP(面向切面编程)框架,Spring作者认为

业务中用到的对象【创建、初始化、销毁】应全部交由Spring管理,从而简化开发代码;

一、IOC

控制权翻转,对象的创建、初始化、销毁全部交由Spring管理;通过动态组件注册、bean对象初始化管理、依赖注入、

bean对象初始化前后进行次要业务组装实现

1.组件配置文件

 1)xml形式




    
    

2)注解形式

 @Configuration修饰的类就相当于一个配置文件

@Configuration//相当于配置文件
public class ApplicationConfig {
//表示xml里面的bean标签value是ID值,这里value中可以是多个值逗号隔开,任何一个值都可以表示这个对象
    @Bean(value={"t1","t2"})
	public Test test1(){
		return new Test();
	}
}

3)获取方式 

AnnotationConfigApplicationContext context =
				  new AnnotationConfigApplicationContext(ApplicationConfig.class);
		  
		  System.out.println("Spring 容器启动了。。。");
		  
		  Test t =(Test)context.getBean("t1");

2.组件注册 

1)@bean: 标识将一个Java类交给Spring管理,@Bean要在【配置类】使用

  • 默认时,以@Bean修饰的bean对象对应的关键字是【方法名】
  • 如果在@Bean指定bean对象对应关键@Bean(value={"a1","a2"}),此时bean对象在Spring容器对应关键字就不是【方法名】,是a1或则a2
  • 所有通过@Bean修饰生成的bean对象默认的情况下都是单例
  • 对于单例的bean对象,可以通过@Lazy延缓变对象被创建时机
    //这个注解专用于单例模式bean对象,此时bean对象不会在spring容器启动时被创建的,
    //只有在一个用户来访时才会被创建
    @Lazy
    @Bean
    public Test test(){
    	return new Test();
    }
  •  bean在生命周期中监听bean对象

(1)可以指定初始化和销毁的方法

//bean类
public class Test {
	
	public void init(){
		System.out.println("实列化对象被初始化");
	}
	
	public void destory(){
		System.out.println("实列化对象被销毁");
	}
}




@Configuration//相当于配置文件
public class ApplicationConfig {
    @Bean(initMethod="init",destroyMethod="destroy")
	public Test test(){
		return new Test();
	}
}

 (2)让bean类文件同时实现InitializingBean接口与DisposableBean接口.根据这两个接口提供的监听方法,来监听当前类的bean的实例化时机和销毁时机

public class Test2 implements InitializingBean,DisposableBean{


	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Test2对象被销毁");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("Test2对象初始化");
	}
}

 (3)在类中指定方法上添加这两个注解,来指定监听bean对象被实例化和销毁的时机@PreDestroy& @PostConstruct

public class Test3 {
	
	public Test3(){
		System.out.println("构造方法被调用");
	}
	
	@PostConstruct
	public void init(){
		System.out.println("Test3对象被初始化");
	}
	@PreDestroy
	public void destroy(){
		System.out.println("Test3对象被销毁");
	}
}

2)@ComponentScan:自动将指定包下的【类】加载到Spring容器 

     (@Controller,@Service,@Resposity,@Compoent);@ComponentScan 要在【配置类】使用

可以将某些类排除在Spring容器之外(excludeFilters属性)

可以将某些类添加到Spring容器之内 (includeFilters属性)

FilterType:扫描过滤策略

  • ANNOTATION 根据注解进行过滤(@Controller,@Service,@Resposity,@Compoent)
  • ASSIGNABLE_TYPE 根据指定类型
  • ASPECTJ表达式过滤
  • REGEX根据正则表达式过滤
  • CUSTOM,根据开发人员自行定义过滤规则
@ComponentScan(value="com.test.beans",excludeFilters={
            		   @Filter(type=FilterType.ANNOTATION,
            				   value={Controller.class,Service.class}),
                       @Filter(type=FilterType.ASSIGNABLE_TYPE,
            		          value={Test01.class}
            		   
               })
//扫描com.test.beans包下类,排除注解@Controller的类,根据指定类型排除类Test01
@Configuration//相当于配置文件
public class ApplicationConfig {

}


//


@ComponentScan(value="com.test.beans",useDefaultFilters=false,includeFilters={
            		   @Filter(type=FilterType.ANNOTATION,
            				   value={Controller.class,Service.class}),
                       @Filter(type=FilterType.ASSIGNABLE_TYPE,
            		          value={Test01.class}
            		   
               })
//扫描com.test.beans包下类去掉默认的过滤规则,扫描@Controller@Service注解的类,根据指定类型扫描类Test01
@Configuration//相当于配置文件
public class ApplicationConfig {

}

 自定义扫描策略如下

/**
**自定义扫描策略
**实现TypeFilter接口.然后重写TypeFilter接口中match方法
**/
public class CustomerFilter implements TypeFilter {

	public boolean match(MetadataReader arg0, MetadataReaderFactory arg1) throws IOException {
		//获取当前bean关联的注解类型
		AnnotationMetadata annotationMetadata = arg0.getAnnotationMetadata();
		String classname = annotationMetadata.getClassName();//获取类名
		//当前类上修饰的注解类型全路劲名
		Set annotationTypes = annotationMetadata.getAnnotationTypes();
		System.out.println();
		for(String str:annotationTypes){
			System.out.println(str+"3543545");
		}
		//获取当前bean类的类型信息
		ClassMetadata classMetadata = arg0.getClassMetadata();
		String cn =classMetadata.getClassName();
		System.out.println("---"+cn);
		if(cn.contains("er")){
			System.out.println("满足要求得类"+cn);
			return true;
		}
		return false;
	}

}
@ComponentScan(value="com.test.beans",useDefaultFilters=false,
             includeFilters={
            		   @Filter(type=FilterType.CUSTOM,
            				   value={CustomerFilter.class})
            		   
               })
@Configuration//相当于配置文件
public class ApplicationConfig2 {

}

 3)@Scope:标识使用单例还是多例模式创建对象,在【配置类】使用,修饰【方法名】,默认单例

@Scope("prototype"):标识多例模式创建对象

@Scope("singleton"):标识单例例模式创建对象

4)@Conditional:按照指定条件来决定bean组件是否会在SpringIoc容器中被注册,在【配置类】使用,修饰【方法名】 

 Conditionnal注解中使用一个使用一个数组,这个数组存放的就是自定义判断条件,开发人员可以通过实现Condition接口,来定义自判断条件.

 @Conditional({自定义条件类型.class})

//linux系统下才实列化对象
public class LinuxCondition implements Condition {

	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		
		  String systemName = context.getEnvironment().getProperty("os.name");
		  if(systemName.contains("Linux")){
			  return true;
		  }
		  return false;
	}

}



//windows系统下才实列化对象
public class WindowsCondition implements Condition {

	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		
		  String systemName = context.getEnvironment().getProperty("os.name");
		  if(systemName.contains("windows")){
			  return true;
		  }
		  return false;
	}

}

//配置类
@Configuration
public class ApplicationConfig {

	@Conditional({LinuxCondition.class})
	@Bean
	public Test test(){
		return new Test();
	}
}



//测试类
public class TestMain {

	public static void main(String[] args) {
		//1.获得Spring容器对象
		  AnnotationConfigApplicationContext context =
				  new AnnotationConfigApplicationContext(ApplicationConfig.class);
		   //2.获得在Spring容器已经注册bean对象,可以发现在windows上运行Test对象未被实列化
		  String beanNames[]= context.getBeanDefinitionNames();
		  for(String beanName:beanNames){
			  System.out.println(beanName);
		  }

	}

}

 5)@import:指定bean导到SpringIOC容器中的一种方式,相当于 spring 配置文件中的 import 标签 ,一般在引入其他配置类时,可以不用再写@Configuration 注解

//指定JdbcConfig类加入Spring IOC作为配置类
@Import(value="com.test.bean.JdbcConfig.class")
@Configuration//相当于配置文件
public class ApplicationConfig {

}

 或者通过实现ImportSelector自定义选择器

//自定义查询器
public class MyImport implements ImportSelector{

	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //添加两个类
		String array[] = {"com.test.beans.Test1","com.test.beans.Test2"};
		return array;
	}

}


//配置文件
@Import(MyImport.class)
@Configuration
public class ApplicationConfig {

}

 6)FactoryBean是Spring容器提供的一种注册bean的方式,通过它来获得组件的bean的对象以及bean对象的单例或则多例的形态

//实现FactoryBean接口
public class MyFactoryBean implements FactoryBean{
	//获取实例对象
	public Test1 getObject() throws Exception {
		// TODO Auto-generated method stub
		return new Test1();
	}
	
	//获取对象类型
	public Class getObjectType() {
		// TODO Auto-generated method stub
		return Test1.class;
	}
	//此方法不重写默认是单列
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return true;
	}
	
	

}
//配置类
@Configuration
public class ApplicationConfig {
	@Bean
	public MyFactoryBean getMyFactoryBean(){
		return new MyFactoryBean();
	}
}

 7)@AutoWired:自动转配(DI)

  • 多个bean存在时,优先使用【类型名】进行赋值
  • 多个bean存在时,可以是@Qualifier指定将某一个bean对象赋值给属性
@Autowired
@Qualifier("userServiceImpl")
private UserService userService;
  • @AuotWired(required=false)

@Autowired注解的时候默认是@Autowired(required=true),表示注入的时候,该bean必须存在,否则就会注入失败;

@Autowired(required=false)表示忽略当前要注入的bean,一般再微服务开发过程中,因为模块分开,可能实现类是在另外一个模块中,此时需要用到这个,否则会装配失败报错

  • 多个bean存在时,可以使@Primary指定优先用于赋值的bean(使用@Primary导致@Qualifier失效)
@Primary//表示优先实列话
@service
public class UserService implements IUserService  {

}

8)@Resource

@Resource其实跟@AutoWired一样的功能,只是提供方不一样,@AutoWired是spring框架中提供的注解,而@Resource是javax.annotation包 提供,JSR250 规范实现

注入方式

@Autowired优先按照类型byType注入

@Resource默认按byName自动注入,也提供按照byType 注入,两个属性name和type

当找不到与名称匹配的 bean 时才按照类型进行装配,但是需要注意的是,如果 name 属性一旦指定,就只会按照名称进行装配

 9)@inject

在javax.inject包 中,JSR330 规范实现的,与@Resource即@Autoware一样,根据类型进行自动装配的,如果需要按名称进行装配,则需要配合@Named; 可以作用对象在setter方法、构造方法、字段上

@Inject标注通过optional参数来定义注入的接口是否需要注入的实现类,默认情况必须显示声明注入接口的实现。

10)@value

给基本类型和 String 类型注入值 ,可以使用占位符获取属性文件中的值

@Value(“${name}”)//name 是 properties 文件中的 key 
private String name;

11)@PropertySource

加载 properties 配置文件,编写在类上面 ,相当于 context:property-placeholder 标签 

属性value[]:用于指定properties文件路径,如果在类路径下,需要写上classpath  

@Configuration 
@PropertySource("classpath:jdbc.properties") 
public class JdbcConfig { 
}

3.BeanPostProcessor后置处理器实现

 BeanPostProcessor是一个接口,主要用于在bean对象初始化前后,做一些辅助功能

接口中包含的方法

postProcessBeforeInitialization:bean被初始化之前工作

postProcessAfterInitialization:被初始化之后工作

//定义自己的process
public class MyBeanPostProcess implements BeanPostProcessor{
	
	public MyBeanPostProcess(){
		System.out.println("构造方法被调用");
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("初始化前"+beanName);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("初始化后"+beanName);
		return bean;
	}
	
	
}

//加入的bean容器中
@Configuration//相当于配置文件
public class ApplicationConfig3 {
    @Bean
	public MyBeanPostProcess myBeanPostProcess(){
		return new MyBeanPostProcess();
	}
}


//测试
public class TestMain3 {

	public static void main(String[] args) {
		//1.获得Spring容器对象
		  AnnotationConfigApplicationContext context =
				  new AnnotationConfigApplicationContext(ApplicationConfig3.class);
		  System.out.println("Spring 容器启动了。。。");
		 //此时容器已启动初始化bean对象会执行MyBeanPostProcess中方法
	}

你可能感兴趣的:(Spring,spring,java)