SpringCore
框架最基础的部分,提供IOC和依赖注入特性
SpringContext
Spring上下文容器,它是BeanFactory功能加强的一个子接口
SpringWeb
提供Web应用开发的支持
SpringMVC
针对Web应用中MVC思想的实现
SpringDao
对JDBC抽象层,简化了JDBC编码,同时,编码更具有健壮性
SpringORM
用于流行的ORM框架的整合,比如:Spring + Hibernate、Spring + MyBatis、Spring + JDO的整合等等。
SpringAop
面向切面编程,它提供了与AOP联盟兼容的编程实现
ApplicationContext 这是spring容器的上下文对象,所有注入的bean都会在容器中,初始化上下文后,就可以通过上下文对象获取容器中的类。
BeanFactory
BeanFactory是接口,提供了OC容器最基本的形式,给具体的IOC容器的实现提供了规范。
BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先
FactoryBean
为IOC容器中Bean的实现提供了更加灵活的方式,FactoryBean在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式(如果想了解装饰模式参考:修饰者模式(装饰者模式,Decoration) 我们可以在getObject()方法中灵活配置。其实在Spring源码中有很多FactoryBean的实现类.
BeanPostProcessor
@Configuration
表明这个类是配置类,可以用annotationConfigApplicationContext加载配置类,初始化配置类的配置。
@ComponentScan
自动扫描包下的相关注解 可以自定义扫描规则
@ComponentScans ComponentScan的集合配置
@Scope 配置容器中的实例生成方式
有几个可选项:
默认是单实例,创建ioc容器的时候,实例bean就被创建了
多实例: 仅当在使用的时候才新建实例
@Lazy 单实例bean默认在容器启动的时候创建对象,如果配置了lazy注解,则会是在使用时候才会创建并初始化,不在容器启动的时候创建对象。
@Conditional
可以根据条件注册bean到容器中,不满足条件就不注入,满足才注入。例如:实现一个只在windows环境才注入的bean
//1.先自定义一个条件类,用于条件匹配,该类实现Conditon接口
public class LinuxCondition implements Condition {
/**
* 只在Linux下才注入的匹配规则
* @param context
* @param metadata
* @return
*/
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
Environment environment = context.getEnvironment();
//获取当前java运行的系统环境
String property = environment.getProperty("os.name");
if (property.toUpperCase().contains(("linux".toUpperCase()))) {
return true;
}
return false;
}
}
//2.使用conditonal注解导入自定义的condition实现类
@Configuration
public class MainConfig3 {
//张三只在windows下才会被注入
@Conditional(WinCondition.class)
@Bean
public Person zhangsan() {
return new Person("zhangsan", 11);
}
//lisi只在windows下才会被注入
@Conditional(LinuxCondition.class)
@Bean
public Person lisi() {
return new Person("lisi", 12);
}
}
以上代码在windows环境中指挥注入zhangsan,在linux环境指挥注入lisi
@Import
使用方式
直接将需要注册的类放入import中。容器会自动注册value里的bean,bean的id为全类名
@Import(value = {Dog.class, Pig.class})
@Import(value = {Dog.class, Pig.class})
@Configuration
public class MainConfig4 {
}
/如果打印容器中所有bean的id,会发现包含如下结果
//cn.ihu.org.demo4.Dog
//cn.ihu.org.demo4.Pig
自定义类,继承ImportSelector,实现selectImports方法。bean的id为全类名
@Import(value = {CustomSelector.class})
public class CustomSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回要导入的类的全类名数组
return new String[] {"cn.ihu.org.demo4.Cat", "cn.ihu.org.demo4.Desk"};
}
}
//如果打印容器中所有bean的id,会发现包含如下结果
//cn.ihu.org.demo4.Cup
//cn.ihu.org.demo4.Desk
自定义类,继承ImportBeanDefinitionRegistrar接口,实现registerBeanDefinitions方法,通过 BeanDefinitionRegistry的实例对象向容器中注入bean。
@Import(value = {CustomBeanDefinitionRegistrar.class})
public class CustomBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata 注解信息
* @param registry 注册类,把需要加入到容器中的类,加入到容器
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println(importingClassMetadata.getAnnotationTypes());
//获取容器中是否注册了Cup类的实例。
boolean b = registry.containsBeanDefinition("cn.ihu.org.demo4.Cup");
//如果容器中有Cup类注册进来了,那么我就再注册一个Water类进去。
if (b) {
//要注册的bean必须包装成RootBeanDefinition类
RootBeanDefinition beanDefinition = new RootBeanDefinition(Water.class);
//向容器中注入一个water类
registry.registerBeanDefinition("water", beanDefinition);
}
}
}
注意:以上三种方式可以放在一起使用,如 @Import(value = {Dog.class, Pig.class, CustomSelector.class, CustomBeanDefinitionRegistrar.class})
@Service
@Component
@Controller
@Repository
以上几个都是用于注入Bean到Spring容器
@Value、@PropertySource、@PropertySources
用于对属性赋值,支持基本字符以及SpringEL表达式
如
@Value(#{20-2})
private Integer age; //会注入值 : 18
也可以用于读取properties文件
//导入配置文件
@PropertySource("clsspath:/test.properties")
@Value("${redis.port}") //可以读取在test.propertes中定义的redis.portd的值
@Autowired、 @Qualified 、@Resources(JSR250)、 @Inject(JSR330,需要导入javax.inject)
@Service
public class TestService {
@Autowired
@Qualifier("testDao2")
TestDao dao;
public TestDao getDao() {
return dao;
}
public void setDao(TestDao dao) {
this.dao = dao;
}
}
@Configuration
@ComponentScan(basePackages = "cn.ihu.org.demo6")
public class Config6 {
@Bean
@Primary//@Primary注解指定注入时的优先级
public TestDao testDao2() {
return new TestDao("2");
}
}
@Service
public class TestService {
@Resource(name = "testDao2")
TestDao dao;
public TestDao getDao() {
return dao;
}
public void setDao(TestDao dao) {
this.dao = dao;
}
}
Bean的生命周期
创建 -> 初始化-> 销毁
我们可以自定义bean的初始化和销毁方法
//1.定义一个类
public class Student {
public void init() {
System.out.println("执行初始化方法...");
};
public void destory() {
System.out.println("执行销毁方法");
}
}
//2.使用bean初始化时候可以指定初始化和销毁方法
@Configuration
public class Mainconfig5 {
@Bean(initMethod = "init", destroyMethod = "destory")
public Student student() {
return new Student();
}
}
可以自定义一个类,实现InitializingBean接口,实现afterPropertiesSet方法,在spring容器创建bean,且为属性赋值之后,会调用。
自定义一个类,实现DisposableBean接口,实现destroy方法,在bean被销毁的时候调用。
//创建对应的类
public class Car implements InitializingBean, DisposableBean {
/**
* 当spring容器销毁时候,会调用
* @throws Exception
*/
public void destroy() throws Exception {
System.out.println("执行bean销毁方法");
}
/**
* Spring容器当中给,当bean创建完成,属性值赋值完成之后,会调用这个方法
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
System.out.println("执行bean初始化方法");
}
public Car() {
System.out.println("创建Bean对象...");
}
}
//初始化bean
@Configuration
public class Mainconfig5 {
@Bean(initMethod = "init", destroyMethod = "destory")
public Student student() {
return new Student();
}
@Bean
public Car car() {
return new Car();
}
}
//spring容器初始化Car类完成,会打印
//执行初始化方法...
//创建Bean对象...
//执行bean初始化方法
可以使用JDK的JSR250标准,使用@PostConstruct、 @PreDestroy
public class School {
@PostConstruct
public void init() {
System.out.println("初始话School");
}
@PreDestroy
public void destroy() {
System.out.println("销毁school....");
}
public School() {
System.out.println("创建school...");
}
}
可以处理类初始化前后需要做的事情。postProcessBeforeInitialization方法会在bean初始话之前执行,postProcessAfterInitialization会在bean初始化之后执行。
```
//将该processor注入容器后,spring就会在加载bean的时候,在执行bean的初始化方法前后分别调用postProcessBeforeInitialization和postProcessAfterInitialization、
@Component
public class CustomProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization:" + beanName);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization:" + beanName);
return bean;
}
}
```
Aware接口提供了一种可以通过BeanPostProcessor处理自定义逻辑的方式,在spring初始化BeanPostProcessor之后,对每一个类进行初始化的时候会检查是否实现了aware接口,然后通过不同的接口调用aware的实现方法。具体过程如下
我们首先定义一个自定义的aware接口实现类,并实现对应方法
@Component
public class CustomAware implements ApplicationContextAware, EnvironmentAware,EmbeddedValueResolverAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println(resolver.resolveStringValue("{{os.name}}"));
}
@Override
public void setEnvironment(Environment environment) {
System.out.println(Arrays.toString(environment.getActiveProfiles()));
}
public ApplicationContext getContext() {
return context;
}
public void setContext(ApplicationContext context) {
this.context = context;
}
}
我们在测试类中可以看到
public class Demo8ConfigTest {
@Test
public void testAwareInterface() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Demo8Config.class);
CustomAware customAware = context.getBean(CustomAware.class);
System.out.println(context == customAware.getContext());//查看注入的容器是否和启动的容器相等,结果是true
}
}
Spring中的源码如下