Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。Spring 包括很多的模块。比如:
Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。Spring Aspects : 该模块为与AspectJ的集成提供支持。Spring AOP :提供了面向切面的编程实现。Spring JDBC : Java数据库连接。Spring JMS :Java消息服务。Spring ORM : 用于支持Hibernate等ORM工具。Spring Web : 为创建Web应用程序提供支持。Spring Test : 提供了对 JUnit 和 TestNG 测试的支持。IoC是Spring最重要的特性之一。控制反转,简单地说就是,创建对象控制权交由Spring来管理,我们不需要手动去创建对象,Spring对自动帮我们创建好。大大的简化了我们应用的开发。
AOP(面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护。AOP是基于动态代理的实现的 ,可以去了解这个设计模式。
单例Bean是存在线程安全问题的,当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。解决办法:可以使用ThreadLocal解决
Bean的生命周期: 创建—初始化—销毁的过程, 容器管理bean的生命周期
Bean容器找到配置文件Spring Bean的定义Bean容器利用Java反射创建一个Bean的实例如果涉及到一些属性值,利用set()方法设置一些属性值如果Bean实现了BeanNameAware接口, 调用setBeanName()方法如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法和上面类型,如果实现了xxxAware接口,调用相应的接口如果有加载这个Bean的容器实现了BeanPostProcessor接口,执行postProcessBeforeInitialization()方法如果Bean实现了InitializingBean接口,调用afterPropertiesSet()方法如果Bean在配置文件中定义 init-method 属性,指定执行的方法如果有加载这个Bean的容器实现了BeanPostProcessor接口,执行postProcessAfterInitialization()方法当销毁Bean的时候, 如果Bean实现了DisposableBean 接口,执行destroy()方法当销毁Bean的时候, 如果Bean在配置文件中定义了destroy-method 属性,指定执行的方法 生命周期创建初始化销毁单实例容器启动的时候创建创建对象完成,赋值后调用初始化方法容器关闭调用销毁方法多实例获取Bean的时候创建创建对象完成,赋值后调用初始化方法容器不会管理这个Bean,不会调用销毁方法 自定义初始化方法和销毁方法,通过@Bean注解初始化和销毁 public class Car { public Car(){ System.out.println("car constructor..."); } public void init(){ System.out.println("car init()..."); } public void destory(){ System.out.println("car destory()..."); } } @Configuration public class MainConfigOfLifeCycle { @Bean(initMethod = "init", destroyMethod = "destory") public Car car(){ return new Car(); } } public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器创建完成..."); applicationContext.close(); } } // 结果为 car constructor... car init()... 容器创建完成... car destory()... 自定义初始化方法和销毁方法,通过InitializingBean、DisposableBean接口定义初始化,销毁方法 @Component public class Cat implements InitializingBean, DisposableBean { public Cat(){ System.out.println("cat...构造器..."); } // 初始化, Bean创建完成,并赋值好后 @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet...初始化..."); } // 销毁方法 @Override public void destroy() throws Exception { System.out.println("destroy...销毁..."); } } @Configuration @ComponentScan("com.aloneness.lifeCycle") public class MainConfigOfLifeCycle { } public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器创建完成..."); applicationContext.close(); } } // 结果为 cat...构造器... afterPropertiesSet...初始化... 容器创建完成... destroy...销毁... 自定义初始化方法和销毁方法,可以使用JSR250的@PostConstruct和@PreDestory注解 @Component public class Dog { public Dog(){ System.out.println("Dog constructor..."); } @PostConstruct public void init(){ System.out.println("Dog...init..."); } @PreDestroy public void destroy(){ System.out.println("Dog...destory"); } } public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器创建完成..."); applicationContext.close(); } } // 结果为 Dog constructor... Dog...init... 容器创建完成... Dog...destory自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory等等)自定义组件实现xxxAware接口 xxxAware:功能使用xxxProcessor
结果
LogAspects类中的logAround方法开始记录日志了...前置div-->[4, 2] div 除法运行... 参数列表是...[4, 2] LogAspects类中的logAround方法开始记录日志了...后置div-->[4, 2] div 除法结束... 除法正常返回...2@Scope 设置Bean的作用域
@Lazy 懒加载,容器启动不创建,第一次使用的时候才会创建对象,并初始化
@Conditional 按条件注册Bean,比如根据不同的操作系统来创建Bean
@Value 赋值,引入配置文件的值 ${}。可以和@PropertySource配合
@PropertySource 引入配置文件@PropertySource(value = {“classpath:person.properties”})
@ComponentScan 组件扫描,配合@Controller/@Service/@Reponitory/@Component注解,给容器注册Bean
@Configuration 表明这个类是配置类,相当于一个xml配置文件,配置@Bean注解,给容器注册Bean
@Qualifier 如果注入的时候多个同类型的Bean,可以使用@Qualifier()指定注入哪一个Bean
@Primary 注入的时候可以优先使用这个Bean装配
@Autowired 自动注入,支持使用@Resource(JSR250) @Inject(JSR330) Java规范
默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class)如果找到多个相同的类型的组件,再将属性的名称作为组件的id去容器中查找@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的的名称,而不是使用属性名@Profile 动态的激活和切换不同的环境
命令行参数 -Dspring.profiles.active=test\dev\prod使用代码的方式激活 @Configuration public class MainConfigOfProfile { @Profile("dev") @Bean public DataSource devDataSource() throws PropertyVetoException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser("root"); comboPooledDataSource.setPassword("123456"); comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver"); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/myshop"); return comboPooledDataSource; } @Profile("prod") @Bean public DataSource prodDataSource() throws PropertyVetoException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser("root"); comboPooledDataSource.setPassword("123456"); comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver"); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/myshop"); return comboPooledDataSource; } }@Import 快速给容器中的导入一个组件
@Import(要导入到容器中的组件), 容器中就会自动注册这个组件,id默认是全类名 @Configuration @Import(value = {Test01.class, Test02.class}) public class MainConfig { @Bean(value = "person") public Person person01(){ return new Person("zhangsan", 23); } } ImportSelector接口: 返回需要导入的组件的全类名 // 返回需要导入的组件 public class MyImportSelector implements ImportSelector { /** * AnnotationMetadata 当前标注@Import注解类的所有注解信息 * * @param importingClassMetadata * @return */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 不要返回null值,会报空指针异常 return new String[]{"com.aloneness.bean.Test03", "com.aloneness.bean.Test04"}; } } @Configuration @Import(value = {Test01.class, Test02.class, MyImportSelector.class}) public class MainConfig { @Bean(value = "person") public Person person01(){ return new Person("zhangsan", 23); } } ImportBeanDefinitionRegistrar public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * 把所有需要添加到容器中的bean, 调用BeanDefinitionRegistry.registerBeanDefinition() 手工注册进来 * * @param importingClassMetadata AnnotationMetadata 当前类的注册信息 * @param registry BeanDefinitionRegistry BeanDefinition的注册类 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean definition = registry.containsBeanDefinition("com.aloneness.bean.Test03"); boolean definition1 = registry.containsBeanDefinition("com.aloneness.bean.Test04"); if(definition && definition1){ RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Test05.class); registry.registerBeanDefinition("test05", rootBeanDefinition); } } } @Configuration @Import(value = {Test01.class, Test02.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig { @Bean(value = "person") public Person person01(){ return new Person("zhangsan", 23); } }