厉害了!10 年架构师整理的 Spring 中升华代码的技巧,让你爱不释手
今日分享开始啦,请大家多多指教~
IOC 创建对象的两种方式
无参构造方式
sprirng 使用无参构造的方式新建对象,然后使用 set 方法注入属性,表现为在 bean.xml 的 property 来对属性进行赋值。
如果实体类中没有 set 方法,property 来对属性进行赋值。
2 有参构造方式
在实体类增加有参构造方法,(无参构造是默认含有的。)
修改 bean.xml 方法
回顾一下 java 的知识,在创建 java 对象时,无参构造函数是默认含有的,但是有参构造函数写了之后,默认的无参构造就会失效,这个时候要使用无参构造需要手动写一个无参构造函数。
spring 配置
1 别名配置
spring 别名的配置规则
<alias name="hello" alias="helloOne"/>
和 mybatis 的有些类似,在 mybatis 中是这样使用的。
配置了别名之后,在 java 代码中就可以通过别名来获取对象实例了。
2 bean 配置
这一个配置文件用 java 代码来解释就是
Hello hello = new Hello();
hello.setName(Spring);
3 多团队协作 import
如果在团队开发中要使用别人写的 xml 文件,可以使用 import 的方式来实现,这样,就可以在自己的 bean 中使用别人 bean 的属性。
<import resource="{path}/beans.xml"/>
依赖注入
依赖注入作为 Spring 实现 IOC 的方式,允许大家使用多种方式来进行 bean 属性值的注入。
1 有参构造器注入
在 4 当中已经实现了构造器注入
2 set 注入
要求被注入的属性 , 必须有 set 方法 , set 方法的方法名由 set + 属性首字母大写 , 如果属性是 boolean 类型, 没有 set 方法 , 是 is .
创建实体类用于测试
Student.java
因为学生对象中含有对象 Address
Address.java
常量注入(常用的数据类型,如 inter,string,double 等)
对象注入
在这里 ref 是引用。
数组注入
list 注入
map 注入
set 注入
property
null 注入
结果
3 使用命名空间注入
P 命名空间注入 : 需要在头文件中假如约束文件
c 命名空间注入 : 需要在头文件中假如约束文件
4 Bean 的作用域
Singleton 单例
Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
Prototype
当一个 bean 的作用域为 Prototype,表示一个 bean 定义对应多个对象实例。Prototype 作用域的 bean 会导致在每次对该 bean 请求时都会创建一个新的 bean 实例。
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
Request
当一个 bean 的作用域为 Request,表示在一次 HTTP 请求中,一个 bean 定义对应一个实例;即每个 HTTP 请求都会有各自的 bean 实例,它们依据某个 bean 定义创建而成。
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
Session
当一个 bean 的作用域为 Session,表示在一个 HTTP Session 中,一个 bean 定义对应一个实例。
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
Bean 的装配与管理
在很多情况下,我们需要在一个类中使用另一个类对象,但是我们已经将对象的创建交给了 Spring 管理。
所以我们需要通过一些方式来对我们的类中的对象属性进行装配,也就是对象注入,其原理方式和属性值的注入类似。
1 通过 ref 来装配
我们现在有三个类
我们必须将三个类注入到 SpringIOC 容器中。
并将 Cat 和 Dog 装配到 Peoson 中才可以正常使用,就和属性值的注入类似。
实质就是将 Cat 和 Dog 实例从 IOC 中取出并赋值给 Peoson 类。
这样手动装配也很方便,但是又更加简便的方式来简化这一过程–>自动装配 autowire。
我们可以使用 xml 配置 , 或者注解的方式来实现自动装配。
2 xml 配置实现自动配置
2.1 byName
只需要通过这种简单的自动装配方式就可以实现之前的功能。它是根据 bean 的 id 来和 set 方法属性名来自动进行匹配的。
2.2 byType
用法一样,这个是通过类的类型来自动装配。因为是通过类型,所以同一类型的对象实例只能同时存在一个。
3 使用注解实现自动装配
jdk1.5 开始支持注解,spring2.5 开始全面支持注解。
第一步我们使用 ref 引用的方式来 bean 实例装配。
第二步我们使用 autowire 的方式来实现 bean 自动装配。
第三步将用注解的方式来实现自动装配。
使用注解方式需要增加一些配置。
在 spring 配置文件中引入 context 头文件。
开启属性注解支持!
3.1 Autowired
@Autowired 是按类型自动转配的,不支持 id 匹配。
需要导入 spring-aop 的包!(已经在 mvc 的 jar 包中导入)
使用方法:
实体类:
bean.xml
@Autowired 默认是通过类型来匹配的,可以理解为 byType 的匹配规则
因为注解方式不是使用 set 的方法来进行注入,所以在实体类中可以不写 set 方法。
3.2 @Qualifier
@Autowired 是根据类型自动装配的,加上 @Qualififier 则可以根据 byName 的方式自动装配
@Qualififier 不能单独使用。
使用方法:
实体类:
bean.xml
通过这么一种方式,就可以实现和 ref 一样的功能。
它也可以写在 set 方法上。
@Autowired(required = false) //这个注解意思是允许参数为空,但是我测试默认他就允许为空,不知道它的意义在哪。
4 使用另一种注解的方式来实现自动配置
4.1 @Resource
@Resource 如有指定的 name 属性,先按该属性进行 byName 方式查找装配;
其次再进行默认的 byName 方式进行装配;
如果以上都不成功,则按 byType 的方式自动装配。
实体类:
bean.xml
通过这样的方式,也可以实现 ref 的功能。
它和**@Autowired 一样可以写在 set 方法**上。
5 @Autowired 与 @Resourse 的异同
同样可以写在属性或者 set 方法上,配合属性使用可以实现 ref 的功能。
@Autowired 属于 spring 规范,默认 byType 的方式匹配
@Resource(属于 J2EE 复返),默认通过 byname 的方式匹配。
注解开发
在 spring 中,虽然可以使用 xml 的方式来进行 bean 的注入,bean 的装配,bean 属性值的注入。但是实际开发用注解进行开发是真的香,而使用 xml 进行 bean 的管理和装配的方式将会逐渐摒弃。
1 准备工作
在完成通过注解的方式来对 bean 进行注入之后,也可以用注解的方式来实现属性的自动注入。
前置环境:
2 bean 注入和属性值赋值
实体类:
可以在属性值上直接注入,但是有 set 方法时建议在 set 方法上注入。
通过 @Value("")的方式直接注入属性值,功能和 bean 中的相同。
@Component 注解和 bean.xml 文件中的 bean 标签作用一样,意思是将这个类交由 spring 容器管理。
通过这种方式将实体类注入 IOC 容器之后不再需要在 bean.xml 中对实体类进行注入。
3 Component 衍生注解
我们这些注解,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!
@Component 三个衍生注解
为了更好的进行分层,Spring 可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。
**@Controller:**web 层
**@Service:**service 层
**@Repository:**dao 层
写上这些注解,就相当于将这个类交给 Spring 管理装配了!
4 bean 的自动装配
在之前的博客有写到在一个 bean 中使用另一个 bean。
而通过这么一种方式,实现了 bean 的装配。结合之前的内容,我们将可以完全摒弃 xml 配置文件的方式来对 bean 进行管理和注入。
注解方式,快捷而优雅
这样配合使用就完成了所有在 bean.xml 中的类和属性注入的所有功能。
5 作用域 @scope
singleton:默认的,Spring 会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收。
6 小结
使用全注解的方式是主流的一种只用方式,在后续的 springboo 中更是常见使用。但是了解 xml 的方式有助于我们使用和理解框架的逐步演进。
xml 方式
注解方式
依赖注入只是 IOC 的一种实现,我们希望将对象的创建和管理交给 Spring 容器管理,这会让我们在管理类的时候不再需要进行复杂的代码更改,而用注入的方式一次性改变
例如:
private SqlService sqlService = new MySqlServiceImpl()
如果我们需要更改实现类,我们需要重新 new 一个对象
private SqlService sqlService = new OracleServiceImpl()
但是依赖注入的方式不同,它是这样实现的
这样节省了我们出创建一个新对象的额外开销。
代理模式
AOP 面向切面编程的底层思想就是代理模式,理解代理模式对理解 AOP 模式很有帮助。
代理模式分为:
静态代理
动态代理
用 UML 图来简单描述一下
1 静态代理
静态代理角色分析
抽象角色 : 一般使用接口或者抽象类来实现
真实角色 : 被代理的角色
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
客户 : 使用代理角色来进行一些操作 .
静态代理实例一:
抽象角色 Rent
真实角色 Host
客户 client
**理解:**代理模式中,真实角色和代理角色共同实现租房这一抽象接口,真正拥有租房权限的是真实角色,因为代理角色找到了真实角色,真实角色将租房这一权限给代理。
**优点:**代理角色除了代理了租房这一功能还可以提供其他的一些附加功能,比如签合同,看房等,这是真实角色不想做的事情,但是却不会影响他本身的租房功能。
静态代理实例二:
抽象接口 UserService
真实角色 UserServiceImpl
代理角色 UserServiceImplProxy
客户端
**理解:**和之前的静态代理案例一一样,通过代理角色的方式,在实现真实角色功能的基础上,不影响地增加一些代理功能。
这也是 AOP 底层的实现机制
2 动态代理
就和在 mybatis 时做分页一样,当分页的类型多的时候,我们不希望为每一种类型都增加一个分页类,这个时候我们使用泛型的方式来实现不同类型数据的返回匹配。
动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK 动态代理
基于类的动态代理–cglib
现在用的比较多的是 javasist 来生成动态代理 . 百度一下 javasist
JDK 的动态代理需要了解两个类
核心 : InvocationHandler 和 Proxy 。
通过这样的方式,我们就可以动态的代理 Rent 这一类的对象了。
除了代理这一类的方法,有时候我们希望能够实现所有对象的代理,这个时候我们可以把 Rent 改为 Object 类型,这样就可以代理所有的对象类型了。
使用方法:
3 小结
就和工具类一样,动态代理可以很方便的动态完成一些有需求变更和频繁使用的工作。
AOP
AOP 作为 spring 的两大核心之一,即面向切面编程,它的底层实现是代理模式,横向的方式来对现有的功能进行加强,使业务逻辑和功能代码更好的脱耦合。
1 Aop 在 Spring 中的作用
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
目标(Target):被通知对象。
代理(Proxy):向目标对象应用通知之后创建的对象。
切入点(PointCut):切面通知 执行的 “地点”的定义。
连接点(JointPoint):与切入点匹配的执行点。
SpringAOP 中,通过 Advice 定义横切逻辑,Spring 中支持 5 种类型的 Advice:
2 AOP 的使用
环境:需要导入 jar 包
第一种方式
通过继承已有的方法,然后通过 AOP 配置文件来设置切入面和执行环绕的方式
抽象接口 UserService
真实角色(房东)
通过这样的一个方式,我们实现了之前和动态代理类似的功能。
第二种方式
有的时候它提供的代理方法可能不是很适配我们的功能需求,我们希望通过自定义代理类的方式来实现代理功能,而不是通过它现有的方法。
自定义的代理类 Proxy
第三种方式
通过注解的方式实现
bean.xml
整合 mybatis
mybatis 实现对数据库操作的高效管理,而 spring 用一种新的方式实现对对象的创建和使用。
整合 mybatis 就是将 mybatis 的数据操纵和 spring 的控制反转结合起来。
导入相关 jar 包
改造 mybatis
原本我们的 mybatis 是有 User 实体类和 UserMapper 接口和 UserMapper.xml,还有 mybatis-config.xml。
主要就是改造 mybatis-config 文件,我们需要把一些 mybatis 连接数据库的操作转移到 spring 中一起操作。
新建一个 spring-config.xml 文件
在这个文件中,我们将 Sqlsession 的获取,对数据库的连接,对 mybatis 的一些配置整合在了一起。
操作 sqlsession
在测试类中用 getbean()方式来获取 session
通过一个 UserMapperImpl 实现类将 session 注入。(规范)
官方文档的规范是使用第二种方式来进行实现的,同时这也更符合 spring 依赖注入的思想。
优化
通过导入的方式将配置部分和普通的 bean 注入分离
将 sqlsession 获取进一步简化。
mybatis-spring1.2.3 版以上才可以使用 .
继承 SqlSessionDaoSupport, 直接利用 getSqlSession() 获得 Sqlsession , 在 bean 管理就直接为 UserMapperIml 注入 SqlSessionFactory(原来是注入 sqlSession) 。
将 sqlSessionFactory 注入即可。
将 UserMapperImpl 分离成 service 层
有一个 UserMapper.xml 后再实现一个 UserMapperImpl 的话逻辑会有些乱,可以将 UserMapperImpl 分离出来,单独建一个 service 层。将 session 的获取在这一个层次进行。
注入 session 类型
继承 SqlSessionDaoSupport 类
获取 sesission 的方式进一步简化:
当我们的获取 Session 的操作更多的时候,我们希望以一种更加高效和更加便于管理的方式去获取 session。
spring 框架提供了一个自动扫描 MapperScannerConfigurer 的操作,它可以通过设置这个类的属性和自动扫描指定包来自动的将我们的 session 注入到包名下的所有 mapper 中。
我们可以直接获取 mapper 去操作,而将 session 的获取交给 spring 封装。
使用方法:
配置文件:
它需要手动地设置两个属性来为指定包名注入 session.
调用
private UserMapper userMapper;
直接调用即可使用。
事务
对于事务的更详细地解释在我的另一篇博客中有显示
事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!
事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。
事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。
事务四个属性 ACID
1.原子性(atomicity)
事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用。
2.一致性(consistency)
一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中。
3.隔离性(isolation)
可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
4.持久性(durability)
事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中。
事务的作用
当我们在操纵数据时,我们在同一个方法执行增删改查操作,我们希望当我们一个操作发生错误时,这个方法内的所有操作都失效。而 spring 的提供的很好的这个管理功能,叫做事务管理。
事务的使用
引入 aop 和 tx 头文件
定义为一个事务管理器,为它绑定数据源
详细配置事务的通知规则
使用 aop 织入
今日份分享已结束,请大家多多包涵和指点!
评论