irpas技术客

Spring学习(IOC、AOP、代理、事务)_大数据 小白学习录

网络投稿 4994

文章目录 @[TOC]认识 Spring 框架简介优点组成常用术语Java Bean IOC和DIIOC 控制反装理解: DI 依赖注入Spring简单配置Spring创建Bean的方式Bean的作用域Spring对Bean的初始化和销毁依赖注入分类注解开发使用Java 的方式去配置Spring 代理模式分类静态代理动态代理 AOP编程**AOP核心概念**AOP在 Spring 中的使用Spring实现AOP Spring的事务管理事务复习Spring的事务使用Spring管理事务 注解:IOC容器创建BeanDI依赖注入配置类AOP 认识 Spring 框架 简介 Spring:春天------>给软件行业带来了春天!2002,首次推出了Spring框架的雏形:interface21框架!Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版。Rod Johnson,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!SSH:Struct2 + Spring + HibernateSSM:SpringMVC + Spring + Mybatis 优点 Spring是一个开源的免费的框架(容器)Spring是一个轻量级的、非入侵式的框架【降低组件之间耦合度 实现解耦】控制反转(IOC),面向切面编程(AOP)支持事务的处理【基于切面和惯例】,对框架整合的支持

总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

组成

常用术语 框架:能完成一定功能的半成品非侵入时设计:从框架角度来说不用继承框架提供的任何类 不影响更换轻量级和重量级:相对来说的,轻量级是非入侵的,依赖的东西少,占用资源少,部署简单等JavaBean:符合 JavaBean 规范的 Java 类POJO:简单老式Java对象容器:装对象的对象。。。管理对象的生命周期 Java Bean 必须是个公有(public)类有无参构造函数用公共方法暴露内部成员属性(getter,setter)

实现这样规范的类,被称为Java Bean。即是一种可重用的组件。

在Spring的IoC容器中,我们把所有组件统称为JavaBean,即配置一个组件就是配置一个Bean。

bean 并不简简单单非要实现JavaBean的规范 其实Spring容器包容性很强 可以处理绝大多数的Java类

Spring Boot 是一个快速开发框架,通过用MAVEN依赖的继承方式,帮助我们快速整合第三方常用框架,完全采用注解化(使用注解方式启动SpringMVC),简化XML配置,内置HTTP服务器(Tomcat,Jetty),最终以Java应用程序进行执行。 Spring Cloud SpringCloud是基于SpringBoot实现的。是一套目前完整的微服务框架,它是是一系列框架的有序集合。它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。 IOC和DI

控制反转是一种设计思想,依赖注入是实现这种设计思想的一种办法。

对象由Spring来创建,管理,装配!

IOC 控制反装 理解:

以往的编程中,对象的创建和对象之间的依赖关系全靠我们自己用编码去实现【程序自己创建实现关系的】,而这里的控制反转就是让我们把创建对象和对象之间的依赖关系这种采用硬编码实现的方式变成第三方去实现,包括用 xml 文件配置 和 注解的方式,这样就不用我们为繁琐的创建对象和对象之间关系去做代码层硬编码的实现了。Spring这个容器就用控制反转这个思想去管理对象的创建和生命周期的,实现的方式就是依赖注入。

控制:传将统的程序自己创建对象的方式变成Spring去创建对象反转:程序本身不去创建对象,而是去接受对象IOC是一种编程思想,由主动的编程变成被动的接收。 DI 依赖注入

一个类是另一个类的一个属性,则这个属性就可以采用 set 方法的方式被注入到这个类中 依赖注入就类似于这种

一个系统中可能会有成千上万个对象。如果要手工维护它们之间的关系,这是不可想象的。我们可以在Spring的XML文件描述它们之间的关系,由Spring自动来注入它们——比如A类的实例需要B类的实例作为参数set进去。

依赖注入就是指用set方法去注入

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

Spring简单配置

配置文件:applicationContext.xml

别名

<!--别名,如果添加了别名,我们也可以使用别名获取到这个对象--> <alias name="user" alias="userNew"/>

Bean的配置

<!-- id:bean的唯一标识符,也就是相当于对象名 class:bean对象所对应的全限定名:包名+类名 name:也是别名,而且name可以同时取多个别名 --> <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3;u4"> <property name="name" value="黑心白莲"/> </bean>

import

它可以将多个配置文件,导入合并为一个。

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://·/artifact/org.aspectj/aspectjweaver*

<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency>

第二步:使用 Spring 的 API 接口实现:

在service包下定义业务接口和业务实现类

package com.gpb.service; public interface UserService { public void add(); public void delete(); public void update(); public void select(); } package com.gpb.service; public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个用户!"); } @Override public void delete() { System.out.println("删除了一个用户!"); } @Override public void update() { System.out.println("修改了一个用户!"); } @Override public void select() { System.out.println("查询一个用户!"); } }

在log包下,定义增强类,一个Log前置增强和一个AfterLog后置增强类

package com.gpb.log; import org.springframework.aop.AfterReturningAdvice; import java.lang.reflect.Method; public class AfterLog implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue); } } package com.gpb.log; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class Log implements MethodBeforeAdvice { /** * @param method 要执行的目标对象的方法 * @param objects 参数 * @param o 目标对象 * @throws Throwable */ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了"); } }

第三步:spring 的配置文件中注册 实现 AOP 的切入 注意导入约束

<!--注册bean--> <bean id="userService" class="com.kuang.service.UserServiceImpl"/> <bean id="log" class="com.kuang.log.Log"/> <bean id="afterLog" class="com.kuang.log.AfterLog"/> <!--方式一:使用原生Spring API接口--> <!--配置aop:需要导入aop的约束--> <aop:config> <!--切入点:expression:表达式,execution(要执行的位置!* * * * *)--> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--执行环绕增加!--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config>

第四步:测试

package com.gpb.test; import com.gpb.service.UserService; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AopTest { ApplicationContext context = null; @Before public void setUp(){ context = new ClassPathXmlApplicationContext("applicationContext.xml"); } @Test public void add(){ // 动态代理的是代理接口 UserService userService = (UserService) context.getBean("userService"); userService.add(); } @After public void tearDown(){ } }

第二种实现方式:自定义类来实现AOP【定义】

其它配置与上面相似

自定义切点类

package com.gpb.pointcut; import org.springframework.stereotype.Component; @Component public class MyCut { public void before(){ System.out.println("======方法执行前======"); } public void after(){ System.out.println("======方法执行后======"); } }

配置

<!-- 自定义切点类 @Component--> <aop:config> <!--自定义切面,ref 要引用的类--> <aop:aspect ref="myCut"> <!--切入点--> <aop:pointcut id="point" expression="execution(* com.gpb.service.UserServiceImpl.*(..))"/> <!--通知--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>

测试

第三种实现方式注解:

定义切面类 【@Aspect】

//声明式事务! @Aspect //标注这个类是一个切面 public class AnnotationPointCut { @Before("execution(* com.kuang.service.UserServiceImpl.*(..))") public void before(){ System.out.println("====方法执行前===="); } @After("execution(* com.kuang.service.UserServiceImpl.*(..))") public void after(){ System.out.println("====方法执行后===="); } //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点; @Around("execution(* com.kuang.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable{ System.out.println("环绕前"); Signature signature = jp.getSignature();// 获得签名 System.out.println("signature:"+signature); Object proceed = jp.proceed(); //执行方法 System.out.println("环绕后"); System.out.println(proceed); } }

配置:

<!--方式三:使用注解--> <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/> <!--开启注解支持! JDK(默认是 proxy-target-class="false") cglib(proxy-target-class="true")--> <aop:aspectj-autoproxy/>

测试

注解的使用:

@EnableAspectJAutoProxy :开启自动代理 这样 切面就能够被织入到Spring管理的类中了

@Aspect :标注该类是个切面

aspect里面有一个order属性,order属性的数字就是横切关注点的顺序

@Before/After("execution(* com.kuang.service.UserServiceImpl.*(..))"):去表示在什么地方之前之后去做

@Pointcut("execution(* com.kuang.service.UserServiceImpl.*(..))") :能够在切面内定义可重用的切点

@Around :创建环绕通知

Spring的事务管理 事务复习

理解

把一组业务当成一个业务来做;要么都成功,要么都失败!

事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!

确保完整性和一致性。

事务ACID原则:

原子性(atomicity)

事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用。

一致性(consistency)

一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中。

隔离性(isolation)

可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。

持久性(durability)

事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中。 Spring的事务

Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

编程式事务管理

将事务管理代码嵌到业务方法中来控制事务的提交和回滚

缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

一般情况下比编程式事务好用。

将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

使用Spring管理事务

头文件的约束导入 : tx**

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

事务配置

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>

通知配置

<!--配置事务通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--给那些方法配置事务--> <!--配置事务的传播特性: new --> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>

配置事务的AOP 横向切入

<!--配置事务切入--> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> 注解: IOC容器创建Bean @Service:业务层的Bean组件@Controller:控制层Bean组件@Repository:持久层的Bean组件@Component:其它Bean组件

? 默认bean的名字是 类首字母小写的

DI依赖注入 @Autowired:依据类型自动注入@Qualifier:辅助上面的 后面要指明名称 用类型+名称来注入bean@Resource:先依据名字去注入 找不到的话再依据类型去注入 配置类 @Configuration:配置类@ImportResource:引入配置文件@Bean:表明Bean组件@Scope:Bean作用域配置【singleton,prototype,session,request...】 AOP @Aspect:表明是一个切面类@Pointcut:表明切入点【execution(* ...方法完全限定名)】@Transform:添加事务


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #文章目录toc认识 #Spring #BeanIOC和DIIOC #控制反装理解DI