Spring简单详解

it2024-03-23  56

简介

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(控制反转) & AOP(面向切面)

IoC是Spring最重要的特性之一。控制反转,简单地说就是,创建对象控制权交由Spring来管理,我们不需要手动去创建对象,Spring对自动帮我们创建好。大大的简化了我们应用的开发。

AOP(面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护。AOP是基于动态代理的实现的 ,可以去了解这个设计模式。

Bean作用域(默认单例)

prototype: 每次获取的时候才会调用方法创建bean。singleton: IoC容器启动会调用方法创建对象放到IoC容器中,这样每次获取都是相同的。request: 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。session: 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。

单例Bean是存在线程安全问题的,当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。解决办法:可以使用ThreadLocal解决

工厂Bean

// 创建一个Spring定义的FactoryBean public class ColorFactoryBean implements FactoryBean<Color> { // 返回一个Color对象,这个对象会添加到容器中 @Override public Color getObject() throws Exception { return new Color(); } @Override public Class<?> getObjectType() { return Color.class; } // true 是单实例 false 是多实例 @Override public boolean isSingleton() { return true; } } @Configuration public class MainConfig { @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } } public class MainTest { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); String[] definitionNames = applicationContext.getBeanDefinitionNames(); for (String name : definitionNames) { System.out.println(name); } // 工厂Bean获取的是getObject()创建的对象 Object colorFactoryBean = applicationContext.getBean("colorFactoryBean"); System.out.println(colorFactoryBean.getClass()); // class com.aloneness.bean.Color // 如果需要获取工厂Bean,需要加上前缀& Object colorFactoryBean1 = applicationContext.getBean("&colorFactoryBean"); System.out.println(colorFactoryBean1.getClass()); // class com.aloneness.bean.ColorFactoryBean } }

Bean的生命周期

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

BeanPostProcessor接口,Bean的后置处理器,用来处理Bean初始化前后的工作

@Component public class MyBeanPostProcessor implements BeanPostProcessor { /** * @param o bean实例 * @param s bean的名字 * @return 返回bean对象 * @throws BeansException */ @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { System.out.println("postProcessBeforeInitialization...初始化前..." + s + "-->" + o); return o; } @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { System.out.println("postProcessAfterInitialization...初始化后..." + s + "-->" + o); return o; } } // 结果为 cat...构造器... postProcessBeforeInitialization...初始化前...cat-->com.aloneness.lifeCycle.Cat@101df177 afterPropertiesSet...初始化... postProcessAfterInitialization...初始化后...cat-->com.aloneness.lifeCycle.Cat@101df177

Aware接口

自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory等等)自定义组件实现xxxAware接口 xxxAware:功能使用xxxProcessor

Spring继承AspectJ实现AOP

引入AspectJ依赖 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency> 定义一个业务类 public class Calculator { public int div(int i, int j) { return i / j; } } 定义一个切面类 @Aspect public class LogAspects { /** * 切点,目标方法 */ @Pointcut("execution(public int com.aloneness.spring.study.aop.Calculator.*(..))") public void pointCut() { } /** * 前置通知 * * @param joinPoint */ @Before("pointCut()") public void logStart(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); System.out.println(joinPoint.getSignature().getName() + " 除法运行... 参数列表是..." + Arrays.asList(args)); } /** * 后置通知 * * @param joinPoint */ @After("pointCut()") public void logEnd(JoinPoint joinPoint){ System.out.println(joinPoint.getSignature().getName() + " 除法结束... "); } /** * 返回通知 * * @param result */ @AfterReturning(value = "pointCut()", returning = "result") public void logReturn(Object result){ System.out.println("除法正常返回..." + result); } /** * 异常通知 * * @param exception */ @AfterThrowing(value = "pointCut()", throwing = "exception") public void logException(Exception exception){ System.out.println("除法异常..." + exception); } /** * 环绕通知 * * @param joinPoint * @return */ @Around("pointCut()") public Object logAround(ProceedingJoinPoint joinPoint){ Object result = null; try{ // 得到方法执行所需的参数 Object[] args = joinPoint.getArgs(); System.out.println("LogAspects类中的logAround方法开始记录日志了...前置" + joinPoint.getSignature().getName() + "-->" + Arrays.asList(args)); // 明确调用业务层方法(切入点方法) result = joinPoint.proceed(args); System.out.println("LogAspects类中的logAround方法开始记录日志了...后置" + joinPoint.getSignature().getName() + "-->" + Arrays.asList(args)); return result; }catch (Throwable t){ System.out.println("LogAspects类中的logAround方法开始记录日志了...异常"); throw new RuntimeException(t); } } } 开启AOP配置,并将两个类注册为Bean @Configuration @EnableAspectJAutoProxy public class AOPConfig { @Bean public Calculator calculator() { return new Calculator(); } @Bean public LogAspects logAspects() { return new LogAspects(); } } 测试AOP切面 public class AOPTest { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AOPConfig.class); Calculator calculator = applicationContext.getBean(Calculator.class); calculator.div(4, 2); } }

结果

LogAspects类中的logAround方法开始记录日志了...前置div-->[4, 2] div 除法运行... 参数列表是...[4, 2] LogAspects类中的logAround方法开始记录日志了...后置div-->[4, 2] div 除法结束... 除法正常返回...2

Spring框架的设计模式

工厂设计模式:通过BeanFactory、ApplicationContext创建Bean单例模式:Spring的Bean默认都是单例代理模式:SpringAOP的实现模板方法:容器刷新refresh()函数

Spring注解大全

@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); } }
最新回复(0)