欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Spring框架基础

时间:2023-06-14
Spring 框架基础 IOC的基本应用 概念 1.什么是IOC

IOC:Inversion of Control (控制反转)。

描述的事情:Java开发领域对象的创建和管理问题。

传统的开发方式:在类A依赖类B的时候,往往会在类A中new一个B对象。

public class A{ B b = new B(); b.hello();}

IOC思想下的开发方式:不用自己去new对象,而是由IOC容器去实例化对象并进行管理。我们需要用到哪个对象,去IOC容器中拿取。

此时,创建和管理对象的权力(控制),交给了外部环境(反转)。

// IOC容器Map map = new HashMap<>();// 往IOC容器中放入已经实例化好的对象map.put("beanName", instance);// 需要使用IOC容器中的对象时map.get("beanName");

2.IOC解决了什么问题

对象之间的耦合问题。

传统的开发方式:

// 定义操作数据库的接口类public interface AccountDao {}// 利用传统JDBC实现操作数据库的接口public class JdbcAccountDaoImpl implements AccountDao {}// 业务逻辑层public class TransferServiceImpl implements TransferService { // 此时操作数据库的方式为 传统的JDBC private AccountDao accountDao = new JdbcAccountDaoImpl();}// 若此时抛弃传统JDBC实现操作数据库 改用Mybatis实现操作数据库public class MybatisAccountDaoImpl implements AccountDao {}// 需要将业务逻辑层代码改为public class TransferServiceImpl implements TransferService { // 此时操作数据库的方式为 Mybatis private AccountDao accountDao = new MybatisAccountDaoImpl();}// 若业务层代码中有“成千上万”个地方需要更换new的对象,此时的工作量会巨大。不符合Java面向接口编程的习惯。

IOC思想下的开发方式:

// 业务逻辑层public class TransferServiceImpl implements TransferService { // 此时只定义需要用到的接口 不去new实现 private AccountDao accountDao;}

3.IOC和DI的区别

DI:Dependancy Injection(依赖注入)。

IOC和DI描述都是对象实例化及依赖关系维护这件事,只是站在的角度不同。IOC是站在对象的角度,将对象实例化和管理的权限交给了容器。DI是站在容器的角度,容器会把对象依赖的其他对象注入。

基本使用 纯XML模式

pom.xml

org.springframework spring-context 5.1.12.RELEASE org.springframework spring-web 5.1.12.RELEASE

resourcesapplicationContext.xml

12 12 value1 value2

public class CreateBeanFactory { // 在静态方法中实例化对象 将自己 new 的对象要放到容器中 public static ConnectionUtils getInstanceStatic() { return new ConnectionUtils(); } // 实例化方法 public ConnectionUtils getInstance() { return new ConnectionUtils(); }}

启动

JavaEE方式

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

JavaSE方式

contextConfigLocation classpath:applicationContext.xml org.springframework.web.context.ContextLoaderListener

XML + 注解模式

resourcesapplicationContext.xml

xml形式对应的注解形式bean标签@Component:注解加载类上。bean的id默认为类名的首字母小写。
@Controller:用于控制层
@Service:用于服务层
@Repository:用于Dao层scope属性@Scope(“prototype”),默认单例,注解加在类上init-method属性@PostConstruct,注解加在⽅法上,该⽅法就是初始化后调⽤的⽅法destroy-method属性@PreDestory,注解加在⽅法上,该⽅法就是销毁前调⽤的⽅法DI依赖注入的方式@Autowired
org.springframework.beans.factory.annotation.Autowired
默认按照类型注入。如果一个类型的实现方式有很多需要配合@Qualififier去告诉Spring配置哪个对象。纯注解模式

@Configuration@ComponentScan({"com.demo"})public class SpringConfig {}

启动

JavaEE方式

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

JavaSE方式

contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext contextConfigLocation com.lagou.edu.SpringConfig org.springframework.web.context.ContextLoaderListener

注解描述@PropertySource引⼊外部属性配置⽂件@import引⼊其他配置类@Value对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息@Bean将⽅法返回对象加⼊ SpringIOC 容器

@Component@PropertySource({"classpath:jdbc.properties"})public class DataSourceConfig { @Value("${jdbc.driver}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; // 自己 new 一个对象 放入 IOC 容器 @Bean public DruidDataSource createDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); druidDataSource.setUsername(username); druidDataSource.setPassword(password); return druidDataSource; } @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }}

高级特性 lazy-init 延迟加载

概念:ApplicationContext 容器的默认行为是在启动服务的时候将所有 singleton 类型的 bean 提前进行实例化。将 lazy-init 设置为 true,bean 将不会再 ApplicationContext 启动时提前被实例化,而是第一次向容器通过 getBean 索取 bean 时实例化。此属性对 scope=“pototype” 的 bean 不生效。

特殊情况:存在两个bean。bean2 设置 lazy-init = true;bean1 设置 lazy-init = false,此时 bean2 会延迟加载。但是若 bean2 被 bean1 引用,在实例化 bean1 的同时,bean2也会被实例化。

FactoryBean

概念:Spring 有两种bean:一种普通的 bean,一种工厂 bean。我们可以借助 FactoryBean 接口生成某一类型的 bean 实例。

// 利用 ResultBean 创建 Result 类型的 beanpublic class ResultBean implements FactoryBean { @Override public Result getObject() throws Exception { Result result = new Result(); return result; } @Override public Class<?> getObjectType() { return Result.class; }}// 获取 Result 类型的 beanapplicationContext.getBean("resultBean");// 获取 ResultBean 工厂 beanapplicationContext.getBean("&resultBean");

SpringBean 的生命周期

1)创建 beanFactory。可以实现 BeanFactoryPostProcessor 接口拿到 beanFactory。

@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("MyBeanFactoryPostProcessor:" + beanFactory); }}

2)初始化BeanPostProcessor。

@Componentpublic class MyBeanPostprocessor implements BeanPostProcessor { public MyBeanPostprocessor() { System.out.println("2)初始化MyBeanPostprocessor"); }}

3)bean的构造方法。

public class LifeCycle implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { public LifeCycle() { System.out.println("3)LifeCycle的构造方法"); }}

4)BeanNameAware 接口。

@Overridepublic void setBeanName(String name) {System.out.println("4)BeanNameAware:" + name);}

5)BeanFactoryAware 接口。

@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("5)BeanFactoryAware:" + beanFactory);}

6)ApplicationContextAware 接口。

@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("6)ApplicationContextAware:" + applicationContext);}

7)BeanPostProcessor 接口的 postProcessBeforeInitialization 方法。

@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("7)postProcessBeforeInitialization:" + beanName); return bean;}

8)@PostConstruct 注解标注的方法。

@PostConstructpublic void PostConstruct() { System.out.println("8)PostConstruct");}

9)InitializingBean 接口的 afterPropertiesSet 方法。

@Overridepublic void afterPropertiesSet() throws Exception { System.out.println("9)InitializingBean:afterPropertiesSet");}

10)xml 中 init-method 方法。

public void initMethod() { System.out.println("10)initMethod");}

11)BeanPostProcessor 接口的 postProcessAfterInitialization 方法。

@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("11)postProcessAfterInitialization:" + beanName); return bean;}

12)ApplicationContext 的创建。

public void TestLifeCycle() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); System.out.println("12)TestLifeCycle:" + context); context.close();}

13)@PreDestroy 注解标注的方法。

@PreDestroypublic void PreDestroy() { System.out.println("13)PreDestroy");}

14)DisposableBean 接口的 destroy 方法。

@Overridepublic void destroy() throws Exception { System.out.println("14)DisposableBean:destroy");}

15)xml 中 destroy-method。

public void destroyMethod() { System.out.println("15)destroyMethod");}

AOP的基本应用 概念 1.什么是AOP

AOP:Aspect Oriented Programming(面向切面编程)。

OOP:Object Oriented Programming(面向对象编程)。

AOP 是 OOP 的延续。OOP 三大特征:封装,继承,多态。是一种垂直继承体系。

OOP开发方式:

Public class Animal { public void eat(){ System.out.println("eating...");} public void run(){ System.out.println("running...");}} Public class Cat extends Animal { // 此时不需要额外的再书写 eat 和 run 方法 解决了大多数代码重复问题 // 然而如果每个 System.out.println() 前后需要增加大量重复的代码 此时 OOP就不能解决代码重复问题 // 而且将业务代码和 日志或性能监控代码混杂在一起,代码臃肿,维护不方便}

AOP优化方式:

public class ProxyFactory { // JDK 动态代理 public Object getJdkProxy(Object obj) { return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return getObject(method, args, obj); } }); } private Object getObject(Method method, Object[] args, Object obj) throws SQLException, IllegalAccessException, InvocationTargetException { // 此处可以编写横切逻辑代码... Object result = null; try { result = method.invoke(obj, args); // 此处可以编写横切逻辑代码... } catch (Exception e) { // 此处可以编写横切逻辑代码... throw e; } return result; } // cglib 动态代理 public Object getCglibProxy(Object obj) { return Enhancer.create(obj.getClass(), new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return getObject(method, objects, obj); } }); }}

2.AOP中的术语 名词解释连接点 Joinpoint可以插入横切逻辑代码的地方切入点 Pointcut已经插入横切逻辑代码的地方通知/增强 Advice横切逻辑代码目标对象 Target被代理的对象代理 Proxy代理对象织入 Weaving插入横切逻辑代码的过程切面 Aspect横切逻辑代码整合后的类3.Spring中AOP的代理选选择

默认情况下,Spring 会根据被代理对象是否实现了接口来选择是否使用 JDK动态代理 还是 cglib动态代理。当没有实现接口的时候选择 cglib 动态代理,当实现接口的时候会选择 JDK官方的代理技术,我们也可以通过配置的方式让 Spring 强制使用 cglib。

基本使用 纯XML模式

pom.xml

org.springframework spring-aop 5.1.12.RELEASE org.aspectj aspectjweaver 1.9.4

resourcesapplicationContext.xml

xmlns:aop="http://www.springframework.org/schema/aop"http://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd

XML + 注解模式

@Component@Aspectpublic class LogUtils { @Pointcut("execution(* com.demo.service.impl.TransferServiceImpl.*(..))") public void pt1() { } @Before("pt1()") public void beforeMethod(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); // 可以拿到 所有传递进来的参数 for (Object arg : args) { System.out.println(arg); } System.out.println("业务逻辑开始执行之前执行......."); } // finally @After("pt1()") public void afterMethod() { System.out.println("业务逻辑结束时执行,无论异常与否都执行......."); } @AfterThrowing("pt1()") public void exceptionMethod() { System.out.println("异常时执行......."); } @AfterReturning(value = "pt1()",returning = "rtValue") public void successMethod(Object rtValue) { System.out.println(rtValue); System.out.println("业务逻辑正常返回时执行......."); }// @Around("pt1()") public void aroundMethod(ProceedingJoinPoint proceedingJoinPoint) { System.out.println("在执行方法之前"); try { // 控制原有业务逻辑是否执行 proceedingJoinPoint.proceed(); System.out.println("在执行方法之后"); } catch (Throwable throwable) { throwable.printStackTrace(); System.out.println("有异常时执行"); } finally { System.out.println("最终执行"); } }}

纯注解模式

@EnableAspectJAutoProxypublic class SpringConfig {}

Spring 声明式事务的支持 事务的四大特性(ACID) 特性描述原子性 atomicity事务是一个不可分割的工作单位,事务中的操作要么同时发生,要么同时失败。一致性 consistency事务必须使数据库从一个一致性状态变换为另一个一致性状态。不会存在一个中间状态。隔离性 isolation当多个用户并发产生事务的时候,每个事务不能被其他事务干扰,事务相互之间隔离。持久性 durability事务一旦提交,改变就是永久性的。事务的隔离级别 不采用隔离级别会发生的事情 错误情况描述脏读事务A 读取到了 事务B **未提交 **的数据。幻读事务A 读取到了 事务B insert 或 delete 提交后 的数据。导致前后读取的条数不一致。不可重复读事务A 读取到了 事务B update提交后 的数据。导致前后读取的内容不一致。数据库定义的四种隔离级别 隔离级别描述串行化 Serializable最高。避免上述三种情况。可重复度 Repeatable Read第二。MySQL的默认隔离级别。可避免脏读和不可重复读。update时会有行锁。读已提交 Read Committed第三。可避免脏读。读未提交 Read Uncommitted第四。无法避免上述三种情况。常用的事务传播行为

事务往往定义在 service 层。如果 service 层方法 A 调用了另一个 service 层方法 B,A 和 B 本身都被添加了事务,那么 A 调用 B 的时候,就需要进行一些协商,这就叫做事务的传播行为。A 调用 B,我们需要站在 B 的角度来定义事务的传播行为。

1)PROPAGATION_REQUIRED:B 如果没有事务,就新建一个事务。如果 A 已经存在一个事务,就加入到A的事务中。这是常见的选则。用于增删改查。

2)PROPAGATION_SUPPORTS:B 支持 A 的事务,如果 B 没有事务,就以非事务方式执行。常用于查询。

基本使用 纯XML模式

pom.xml

org.springframework spring-aop 5.1.12.RELEASE org.aspectj aspectjweaver 1.9.4 org.springframework spring-jdbc 5.1.12.RELEASE org.springframework spring-tx 5.1.12.RELEASE

resources/applicationContext.xml

xmlns:tx="http://www.springframework.org/schema/tx"http://www.springframework.org/schema/txhttps://www.springframework.org/schema/tx/spring-tx.xsd

XML + 注解模式

resources/applicationContext.xml

@Service("transferService")public class TransferServiceImpl implements TransferService {@Override // 配置声明式事务 注解里面有默认值 @Transactional public void transfer() throws Exception { }}

纯注解模式

@Configuration@ComponentScan({"com.demo"})@EnableTransactionManagementpublic class SpringConfig {}// 自己 new 一个对象 放入 IOC 容器@Beanpublic DruidDataSource createDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); druidDataSource.setUsername(username); druidDataSource.setPassword(password); return druidDataSource;}// JdbcTemplate 放入容器@Beanpublic JdbcTemplate createJdbcTemplate(DruidDataSource druidDataSource) { return new JdbcTemplate(druidDataSource);}// DataSourceTransactionManager 声明式事务放入容器@Beanpublic DataSourceTransactionManager dataSourceTransactionManager(DruidDataSource druidDataSource) { return new DataSourceTransactionManager(druidDataSource);}

参考git:https://gitee.com/zhangyizhou/learning-spring-demo.git

1.自定义 ioc 和 aop 项目:lagou-transfer

1.spring ioc 纯xml项目:lagou-transfer-iocxml

2.spring ioc xml +注解项目;aop 纯xml项目:lagou-transfer-ioc-xml-anno

3.spring ioc+aop 纯注解项目:lagou-transfer-ioc-anno

4.spring 声明周期项目:lagou-spring-life-cycle

5.声明式事务项目:lagou-transfer-transaction

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。