1、spring简介

梦想不抛弃苦心追求的人,只要不停止追求,你们会沐浴在梦想的光辉之中。再美好的梦想与目标,再完美的计划和方案,如果不能尽快在行动中落实,最终只能是纸上谈兵,空想一番。只要瞄准了大方向,坚持不懈地做下去,才能够扫除挡在梦想前面的障碍,实现美好的人生蓝图。1、spring简介,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、Spring整体框架

在这里插入图片描述

二、Spring IOC

1、核心思想

资源不由资源使用者直接管理,而是由第三方管理,使用时通过第三方获取,这个第三方就是ioc容器。

代码意思就是,使用时通过自动装配的方式从ioc容器中获取,而不是直接new出相应对象

public class UserService{
 @AutoWired
 private UserDao userDao;
 //而不是new出来
}

好处:
1、资源集中管理,实现资源的可配置和易管理。
2、降低耦合度,降低了使用资源双方的依赖程度。

2、bean的生命周期

2.1、生命周期分类

bean的创建—–>初始化—–>销毁

2.2、设置bean的初始化和销毁方法

A、通过@bean注解,指定init-method和destory-method参数。具体方法写在bean类中,代码如下

@Configuration 
public class MainConfig { /
	/指定了bean的生命周期的初始化方法和销毁方法.
	@Bean(initMethod = "init",destroyMethod ="destroy") 	
	public Car car() { 
		return new Car(); 
	} 
}
public class car {
	public car(){
		System.out.println("car的构造方法"); 
	}
	
	public void init(){
		System.out.println("car的初始化方法"); 
	}

	public void destroy(){
		System.out.println("car的销毁方法"); 
	}
}

B、通过让bean实现InitializingBean和DisposableBean接口重写初始化和销毁方法,在类上用@Component等注解,注册到ioc容器中。代码如下

@Component
public class Person implements InitializingBean,DisposableBean {
	public Person() { 
		System.out.println("Person的构造方法"); 
	}

	@Override 
	public void afterPropertiesSet() throws Exception { 	
		System.out.println("person的初始化方法"); 
	}

	@Override 
	public void destroy() throws Exception { 	
		System.out.println("person的销毁方法"); 
	}
}

C、通过Spring的BeanPostProcessor的 bean的后置处理器来拦截所有bean创建过程

@Component 
public class TulingBeanPostProcessor implements BeanPostProcessor { 
	//在init方法之前调用
	@Override 
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	 	System.out.println("TulingBeanPostProcessor...postProcessBeforeInitialization:"+beanName); 
	 	return bean; 
	 }

	//在init方法之后调用
	@Override 
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	 	System.out.println("TulingBeanPostProcessor...postProcessAfterInitialization:"+beanName); 
	 	return bean; 
	 } 
}

注意:BeanPostProcessor在bean的初始化前后工作,主要用于修改bean的属性

2.3、调初始化和销毁方法的时机

单实例模式:容器启动时,先创建对象,然后赋值,之后调初始化方法。容器关闭时调销毁方法
多实例模式:对象的创建、初始化、销毁都不受容器控制。而是在获取bean的时候创建对象、调初始化方法;不用时调销毁方法

3、常用注解

3.1、往ioc容器中添加组件的注解

A、@CompentScan +@Controller @Service @Respository @compent。适用于针对我们自己写的组件。代码如下

@Configuration 
@ComponentScan(basePackages = {"com.tuling.testcompentscan"}) 
public class MainConfig {}
@Component
public class Person {}

注意:单纯的@Controller @Service @Respository @compent并不会往ioc容器中加组件,必须配合包扫描@CompentScan

扩展:包扫描注解@CompentScan的详细用法,代码如下
a、排除用法:排除@Controller注解修饰的和TulingService类的

@Configuration
@ComponentScan(basePackages = {"com.tuling.testcompentscan"},excludeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
	@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {TulingService.class})
})
public class MainConfig {}

b、指定用法:指定只注入@Controller @Service注解修饰的

@Configuration
@ComponentScan(basePackages = {"com.tuling.testcompentscan"},includeFilters = {
	@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class, Service.class})
},useDefaultFilters = false)
public class MainConfig {}

注意,若使用指定用法,需要把useDefaultFilters属性设置为false(true表示扫描全部的)

B、@Bean。适用于导入第三方组件的类。代码如下

@Configuration 
public class MainConfig { 
	@Bean 
	public Person person(){ 
		return new Person(); 
	} 
}

扩展:
a、配置bean的作用域:@Scope。

//在不指定@Scope的情况下,所有的bean都是单实例的bean,而且是饿汉加载(容器启动实例就创建好了)
@Bean 
public Person person() { 
	return new Person(); 
}

//指定@Scope为 prototype 表示为多实例的,而且还是懒汉模式加载(IOC容器启动的时候,并不会创建对象,而是在第一次使用的时候才会创建)
@Bean 
@Scope(value = "prototype") 
public Person person() { 
	return new Person(); 
}


// singleton 单实例的(默认) 
// prototype 多实例的 
// request 同一次请求 
// session 同一个会话级别

b、bean的懒加载:@Lazy(主要针对单实例的bean。 容器启动的时候,不创建对象,在第一次使用的时候才会创建该对象)

@Bean 
@Lazy 
public Person person() { 
	return new Person();
}

c、符合条件才创建bean:@Conditional
场景:有二个组件TulingAspect 和TulingLog ,TulingLog组件是依赖于TulingAspect的组件,代码如下

//先定义判断条件
public class TulingCondition implements Condition {
	/**
	 * @param context 
	 * @param metadata 
	 * @return 
	 */ 
	 @Override
	 public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
	 		//判断容器中是否有tulingAspect的组件
	 	 	if(context.getBeanFactory().containsBean("tulingAspect")) { 	
	 	 		return true; 
	 	 	}
	 	 	return false;
	 } 
}
@Configuration
public class MainConfig { 
	@Bean public TulingAspect tulingAspect() { 
		return new TulingAspect(); 
	}

	//如果容器中有tulingAspect的组件,那么tulingLog才会被实例化.
	@Bean 
	@Conditional(value = TulingCondition.class) 
	public TulingLog tulingLog() { 
		return new TulingLog(); 
	} 
}

C、@Import。适用于导入第三方组件的类。代码如下

@Configuration 
@Import(value = {Person.class, Car.class}) 
public class MainConfig { }

扩展:
a、通过@Import 的ImportSeletor类实现组件的导入 (导入组件的id为全类名路径)

public class TulingImportSelector implements ImportSelector { 
	//可以获取导入类的注解信息 
	@Override 
	public String[] selectImports(AnnotationMetadata importingClassMetadata) { 
		return new String[]{"com.tuling.testimport.compent.Dog"}; 
	} 
}
@Configuration
@Import(value = {Person.class, Car.class, TulingImportSelector.class}) 
public class MainConfig { }

b、通过@Import的 ImportBeanDefinitionRegister导入组件 (可以指定bean的名称)

public class TulingBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { 
	@Override 
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 
		//创建一个bean定义对象 
		RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class); 
		//把bean定义对象导入到容器中 
		registry.registerBeanDefinition("cat",rootBeanDefinition); 
	} 
}
@Configuration 
@Import(value = {Person.class, Car.class, TulingImportSelector.class, TulingBeanDefinitionRegister.class}) 
public class MainConfig { }

D、通过实现FacotryBean接口来实现组件注册。适用于要注册的组件初始化复杂时,因为可以在getObject中写逻辑来进行复杂的初始化,别的方法均不可

public class CarFactoryBean implements FactoryBean<Car> { 
	//返回bean的对象 
	@Override public Car getObject() throws Exception { 
	return new Car(); 
	}

	//返回bean的类型 
	@Override 
	public Class<?> getObjectType() { 
		return Car.class; 
	}

	//是否为单利 
	@Override 
	public boolean isSingleton() { 
		return true; 
	}
}
@Configuration 
public class MainConfig { 
   @Bean 
   public CarFactoryBean carFactoryBean(){ 
       return new CarFactoryBean(); 
   }
}

注意:此时正常通过组件名carFactoryBean获取到的其实是Car对象,要想获取
CarFactoryBean对象则通过组件名&carFactoryBean获取

3.2、自动装配注解:@AutoWired

//一个Dao 
@Repository 
public class TulingDao { }

@Service 
public class TulingService { 
	@Autowired 
	private TulingDao tulingDao;

结论:自动装配首先是按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照属性名称来进行装配

扩展:
a、强制指定特定名字的组件进行装配:@Qualifier

@Autowired 
@Qualifier("tulingDao") 
private TulingDao tulingDao2;

b、没有相应组件便会抛出异常,如不想抛异常,则required = false

@Autowired(required = false)
@Qualifier("tulingDao") 
private TulingDao tulingDao2;

3.3、给组件赋值注解

A、@Value

public class Person { 
	//通过普通的方式 
	@Value("司马") 
	private String firstName; 
	//spel方式来赋值 
	@Value("#{28-8}") 
	private Integer age; 
	//通过读取外部配置文件的值 
	@Value("${person.lastName}") 
	private String lastName; 
}

B、@PropertySource

@Configuration 
@PropertySource(value = {"classpath:person.properties"}) //指定外部文件的位置
public class MainConfig { 
	@Bean 
	public Person person() { 
		return new Person(); 
	} 
}

注意:person.properties中的属性要和person类中的属性一一对应

3.4、根据环境来激活不同的Bean注解:@Profile

@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效
@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活
没有标志为@Profile的bean 不管在什么环境都可以被激活

//标识为测试环境才会被装配 
@Bean 
@Profile(value = "test") 
public DataSource testDs() { 
	return buliderDataSource(new DruidDataSource()); 
}


//标识为开发环境才会被激活 
@Bean 
@Profile(value = "dev") 
public DataSource devDs() { 
	return buliderDataSource(new DruidDataSource()); 
}

扩展:切换环境的方法
a、通过运行时jvm参数来切换 -Dspring.profiles.active=test|dev|prod
b、通过代码的方式来激活

public static void main(String[] args) {
	AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 	
	ctx.getEnvironment().setActiveProfiles("test","dev"); 
	ctx.register(MainConfig.class); 
	ctx.refresh(); 
	printBeanName(ctx); 
}

4、 我们自己的组件 需要使用spring ioc的底层组件的时候,比如 ApplicationContext等,我们可以通过实现XXXAware接口来实现

@Component 
public class TulingCompent implements ApplicationContextAware,BeanNameAware { 
	private ApplicationContext applicationContext; 
	@Override 
	public void setBeanName(String name) { 
		System.out.println("current bean name is :【"+name+"】"); 
	}

	@Override 
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
		this.applicationContext = applicationContext; 
	} 
}

三、Spring AOP

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153474.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!