spring+mybatis
Spring之IOC
一、第一个例子总结
(通过id获取bean实例)
- person对象是什么时候被创建的(构建空参构造器)
- 同一个类在容器中是单实例
- 如果容器中没有注册对象,则异常
- ioc容器中bean里的property里的name属性值由javabean中set/get方法所决定
二、根据bean类型获取bean实例
- 如果ioc.xml中有一个类型的两个实例,按照类找结果是什么?
(1)报错———single
(2)解决,按ID找。但如果ID一样怎么办?getbean(“ID”,类.class)
三、构造器注入
通过构造器为bean属性赋值
<constructor-arg name="" value=""></constructor-arg>
<constructor-arg value=""></constructor-arg>
注意:可以省略name属性,此时顺序严格按照构造器变量声明的顺序。
<constructor-arg value="" index=""></constructor-arg>
注意:省略name属性,可以按照index属性值给相应变量赋值。
<constructor-arg value="" index="" type=""></constructor-arg>
注意:如果构造器重载、又省略name属性,可以按照index属性值及type属性值给相应变量赋值。
四、p命名空间
命名空间:xml中为了区分重复的标签(如name)
<bean id="" class="" p:属性名1="" p:属性名2="" p:属性名3=""></bean>
五、为复杂数据类型赋值
- 给某个属性赋null值
<property name="属性名"></null></property>
-
为属性为对象的赋值
(1)已知ioc.xml配置文件中已经有该属性的对象(引用外部bean)
<property name="属性为对象的属性名" ref="IOC中已有的对象的ID值"></property>
(2)引用内部bean
<property name="属性为对象的属性名">
<bean class="属性为对象的类">//注意:该bean不管是否指定id或者name,该bean都有 一个唯一的匿名标识符,该bean对其他外部的bean不可见。
<property name="属性名" value="" ></property>
</bean>
</property>
- 为list类型赋值
(1)第一种方式:内部bean
<property name="list">
<list>
<bean class="com.xngao.test.Book" p:bookName="水浒" p:author="罗贯中"></bean>
</list>
</property>
(2)第二种方式:引用外部bean
<property name="list">
<list>
<ref bean="IOC容器中已有的对象的ID值:如book01"/>
</list>
</property>
- 为map类型赋值
(1)使用entry中的key,value
<property name="maps">
<map>
<entry key="01" value="zhangsan"></entry>
<entry key="02" value="lisi"></entry>
</map>
</property>
(2)使用entry中的key,value-ref
<property name="maps">
<map>
<entry key="01" value-ref="book01"></entry>
</map>
</property>
(3)使用内部bean
<property name="maps">
<map >
<entry key="01">
<bean class="com.xngao.test.Book" p:bookName="水浒" p:author="罗贯中"></bean>
</entry>
</map>
</property>
(4)使用util名称空间创建外部引用
<util:map id="mymap">
<entry key="01" value="zhangsan"></entry>
<entry key="02" value="lisi"></entry>
<entry key="03" value-ref="book01"></entry>
<entry key="04">
<bean class="com.xngao.test.Book" p:bookName="水浒" p:author="罗贯中"></bean>
</entry>
</util:map>
<bean id="person04" class="com.xngao.test.Person">
<property name="maps" ref="mymap"></property>
</bean>
六、级联属性
使用级联属性为属性赋值
<property name="属性名.级联属性名" value="属性值" ></property>
注意:如果引用的是外部bean,用此法可以修改外部bean里的属性值。
七、bean的继承
通过继承实现bean的配置
<bean id="person05" class="com.xngao.test.Person" parent="person02">
<property name="name" value="张三"></property> //这是要改的属性值
</bean>
八、abstract属性
通过abstract属性创建模板bean
<bean id="person02" class="com.xngao.test.Person" abstract="true">
<property name="name" value="李四"></property>
<property name="age" value="23"></property>
<property name="sex" value="男"></property>
</bean>
九、bean之间的依赖
(改变bean创建的顺序)
<bean id="person" class="com.xngao.test.Person" depends-on="ID值1,ID值2"></bean>
<bean id="ID值1" class="com.xngao.test.Car"></bean>
<bean id="ID值2" class="java.awt.print.Book"></bean>
十、创建单实例与多实例的bean
十一、通过工厂创建bean
- 静态工厂:在获取对象名方法(此方法为静态方法)中创建需要创建获取对象的对象,然后在外部,工厂本身不用去创建本身工厂对象,而是通过静态方法的调用实现对象的创建(获取)。
对象 = 工厂类.获取对象名方法(创建的对象参数)
<bean id="book02" class="com.xngao.test.StaticFactory" factory-method="getBookStaticFactory">
<constructor-arg value="西游记"></constructor-arg>
</bean>
- 实例工厂:在获取对象名方法中创建需要创建获取对象的对象,然后在外部工厂本身创建本身工厂对象,然后在通过获取对象名方法调用实现对象的创建(获取)。
工厂类 工厂对象 = new 工厂类()
工厂对象. 获取对象名方法(创建的对象参数)
第一步创建实例工厂对象:
<bean id="instancefactory01" class="com.xngao.test.InstanceFactory">
</bean>
第二步根据实例工厂创建所需对象
<bean id="book03" class="com.xngao.test.Book" factory-bean="instancefactory01"
factory-method="getBookFactory">
<constructor-arg value="西游记"></constructor-arg>
</bean>
十二、通过实现factorybean创建对象
第一步:创建实现FactoryBean接口的类
public class FactoryBeanBook implements FactoryBean<Book> {
}
第二步:写配置
<bean id="FactoryBeanBook" class="com.xngao.test.FactoryBeanBook"></bean>
注意:测试的时候不能强转。
十三、bean的生命周期
- 单例:容器创建调用构造器创建----获取bean是调用初始化方法------容器关闭调用销毁方法(容器只要创建就会创建bean对象)
- 多例:获取bean是调用构造器创建及初始化方法(多例容器创建时不会创建bean对象,只有获取bean时才创建对象)
<bean id="book04" class="com.xngao.test.Book" destroy-method="getDestory" init-method="getInit"></bean>
注意:容器销毁需用ConfigurableApplicationContext接口获取ioc容器、测试的时候不能强转。
十四、后置处理器
BeanPostProcessor接口
在bean初始化前后可以进行方法的执行。
十五、数据库连接
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="jdbcUrl" value="jabc:mysql://localhost:3306/gggg"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
十六、基于XML的自动装配
(为属性为对象的属性自动赋值)
- autowire属性:
- byName:通过名字自动赋值(注意:是属性的名字,如果不一样会怎样?)
- byType:通过类型自动赋值(如果ioc中有多个一个类的bean,会怎样?如果ioc中没有要找的类的bean呢?)
- constructor:通过有参构造器自动赋值(创建要获取的bean的有参构造器,传入要赋值的属性)
<bean id="person01" class="com.xngao.test1.Person" autowire="constructor">
<!-- <property name="car" ref="car01"></property> -->
</bean>
属性为list实例:
<bean id="person01" class="com.xngao.test1.Person" autowire="byType"></bean>
<bean id="book01" class="com.xngao.test1.Book">
<property name="bookname" value="sanguo"></property>
</bean>
<bean id="book02" class="com.xngao.test1.Book">
<property name="bookname" value="sanguo"></property>
</bean>
十六、SpEL表达式
语法格式:
#{}:给属性赋值。如:#{5}、#{3.4}、#{“张三”}、#{false}、#{car01}、#{person01.name}
#{T(类的全路径).方法名(参数)}:调用静态方法
<!-- <bean id="staticAge" class="com.xngao.test1.StaticAge"></bean> -->
<bean id="person02" class="com.xngao.test1.Person">
<property name="age" value="#{T(com.xngao.test1.StaticAge).getAge()}"></property>
</bean>
#{对象id.方法名(参数)}:调用非静态方法
<bean id="staticAge" class="com.xngao.test1.StaticAge"></bean>
<bean id="person02" class="com.xngao.test1.Person">
<property name="age" value="#{staticAge.getAge()}"></property>
</bean>
十七、@Component注解
spring提供的四个注解:
- @Controller:控制器,控制网站的跳转,也就是servlet
- @Service:业务逻辑
- @Repository:数据层也称持久层
- @Component:给不属于以上三层使用
配置context命名空间
<context:component-scan base-package="com.xngao.test1"></context:component-scan>
导入AOP包
默认的ID为类名首字符小写(改id名如:@repository:(“aaa”)
)
改变多实例:@Scope(value="prototype")
十八、扫描包
通过context:exclude-filter扫描不包含的类,通过context:include-filter扫描包含的类
- 语法格式:排除
<context:component-scan base-package="com.xngao.test1">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
- 语法格式:添加
<context:component-scan base-package="com.xngao.test1" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
{
type="annotation":指定排除(添加)规则,按照注解进行排除(添加)。
expression="":值,写的是注解的全类名。
}
{
type="assignable":指定排除(添加)某个具体的类。
expression="":值,写的是要排除(添加)的类的全类名。
}
十九、@Autowired注解
使用@Autowired注解实现根据类型自动装配
-
@Autowired:为需要自动赋值的属性上添加此注解。也可以为方法添加。
-
@Autowired实现步骤:
- 按照类型去容器中找到相应的组件。
- 如果找到一个就匹配;
- 如果没找到就报错;
- 如果找到多个则按照类里的变量名(类名首字符小写)作为默认id进行匹配;
- 如果变量名(不是以类名首字符小写定义的)与默认id不匹配,则使用@Qualifier(“”),将类变量名(不是以类名首字符小写定义的)设置为已有的默认id值。如:@Qualifier(“bookDao”)
- 按照类型去容器中找不到相应的组件,可使用@Autowired(required=false)给赋null
- 按照类型去容器中找到相应的组件。
-
@Resourse:javaee标准、@Autowired:spring标准
Spring之AOP
一、概念
-
面向切面编程,指程序在运行期间,将某段代码动态的切入到某个方法指定的位置进行运行的编程方式。
-
场景:给计算器添加日志记录
1、直接在源码中加
2、写一个Utils工具类
3、动态代理:代码自己写困难、如果被代理对象没有实现任何接口,则动态代理无法自动创建代理对象。
二、几个专业术语
- 切面
切面(Aspect)是指封装横切到系统功能(如事务处理)的类。 - 连接点(比如方法的开始、方法的返回、方法的异常、方法的结束)
连接点(Joinpoint)是指程序运行中的一些时间点,如方法的调用或异常的抛出。 - 切入点
切入点(Pointcut)是指那些需要处理的连接点。在Spring AOP 中,所有的方法执行都是连接点,而切入点是一个描述信息,它修饰的 是连接点,通过切入点确定哪些连接点需要被处理。 - 通知(增强处理)
由切面添加到特定的连接点(满足切入点规则)的一段代码,即在定义好的切入点处所要执行的程序代码。可以将其理解为切面开启后,切面的方法。因此,通知是切面的具体实现。 - 引入
引入(Introduction)允许在现有的实现类中添加自定义的方法和属性。 - 目标对象
目标对象(Target Object)是指允许添加通知的通知的对象。如果AOP 框架使用运行时代理的方式(动态的AOP)来实现切面,那么通知对象总是一个代理对象。 - 代理
代理(Proxy)是通知应用到目标对象之后,被动态创建的对象。
三、AOP使用步骤
1、导包
10个包,除了spring提供的7个包之外,还需导入第三方提供的3个包(就算被代理对象没有实现任何接口,aop也可以自动创建代理对象)。
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
2、写配置
-
将目标类和切面类(封装了通知的类)加入到ioc容器中。
-
告诉ioc容器那个是切面类,通过@Aspect注解实现。
-
告诉spring切面类里面的通知是什么时候,在什么位置运行。
@Before:在目标方法执行之前运行 前置通知
@After:在目标方法结束之后运行 后置通知
@AfterReturning:在目标方法返回值后执行 返回通知
@AfterThrowing:在目标方法抛出异常后执行 异常通知
@Around:环绕 环绕通知
-
切入点表达式:execution(权限修饰符 返回值数据类型 类的全类名)
如:( *:指的是所有。)
@Before("execution(public int com.xngao.testt.SiXianCacultor.add(int, int))")
或
@Before("execution(public int com.xngao.testt.SiXianCacultor.*(int, int))")
- 开启基于注解AOP功能:aop名称空间
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
3、测试
用类型一定要用接口类型。
四、切入点表达式
execution(权限修饰符 返回值数据类型 类的全类名)
1、两个通配符:*、…
如:
@Before("execution(public int com.xngao.testt.SiXianCacul*r.*(int, *))")
或
@Before("execution(public int com.xngao.testt.SiXianCacultor.*(..))")
@Before("execution(* *(..))"):模糊写法,但不赞成。
&& || !
2、抽取可重用切入点表达式
-
创建一个返回值为void的、没有实现的方法。
-
给方法上加注解@pointcut
如:
@Pointcut("execution(public int com.xngao.testt.SiXianCacultor.add(int, int))")
public void aaa(){};
引用方法:@Before("aaa()")
五、JoinPoint参数
封装了当前目标方法的详细信息。
使用joinPoint.getArgs()获取目标方法参数信息。
使用joinPoint.getSignature()获取目标方法的签名。
使用切入点表达式中的returning="xxx"属性设置获取返回值。
使用切入点表达式中的throwing="xxx"属性设置获取异常信息。
六、环绕通知
环绕通知利用ProceedingJoinPoint pjp参数实现动态代理。使用pjp.proceed()方法控制这目标方法的执行。
七、多切面
先进后出,以英文字母的顺序先后执行,或使用@order(数值)改变顺序,数值越小优先级越高,环绕优先。
八、基于配置的AOP
1、把类注册到ioc容器中
2、告诉ioc谁是切面类
<aop:config>
<aop:aspect ref="riZhiUtils"></aop:aspect>
</aop:config>
3、引入通知
<aop:config>
<aop:aspect ref="riZhiUtils">
<aop:before method="logStart" pointcut="execution(public int com.xngao.testt.SiXianCacultor.add(int, int))"/>
</aop:aspect>
</aop:config>
重要的用配置,不重要的用注解。
九、JdbcTemplate
1、配置数据源:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ggg"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>
2、获取连接:
DataSource bean = ioc.getBean(DataSource.class);
Connection connection = bean.getConnection();
3、更新:
JdbcTemplate bean = ioc.getBean(JdbcTemplate.class);
String sql = "update t_ggg set name=? where id=1" ;
int update = bean.update(sql, "gao");
4、插入:
String sql = "insert into t_ggg(name,sex,email) values(?,?,?)";
List<Object[]> batchArgs = new ArrayList<Object[]>();
batchArgs.add(new Object[]{"wangwu","n","wangwu@163.com"});
int[] batchUpdate = bean.batchUpdate(sql, batchArgs);
for (int i : batchUpdate) {
System.out.println(i);
}
5、查询并封装成一个对象:
String sql = "select * from t_ggg where id=?";
Person queryForObject = bean.queryForObject(sql, new BeanPropertyRowMapper<>(Person.class), 10);
System.out.println(queryForObject);
6、删除:
String sql = "delete from t_ggg where id=10";
bean.batchUpdate(sql);
十、事务管理(基于注解)
1、DataSourceTransactionManager
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2、transactionManager
<tx:annotation-driven transaction-manager="transactionManager"/>
3、注解
@Transactional
十一、事务管理(基于xml)
<aop:config>
<aop:pointcut expression="execution(* day2022*.*.*(..))" id="aaa"/>
<aop:advisor advice-ref="bbb" pointcut-ref="aaa"/>
</aop:config>
<tx:advice id="bbb" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
MyBatis
一、概述
(3.x以前版本称iBatis)
1、与数据库进行交互,原生JDBC—持久化层的框架(sql映射框架)—ORM映射
下载:GitHub
2、环境搭建
- 1)数据库相关资源、javabean、Dao接口
- 2)导包:mybatis、数据库驱动、日志包。log4j.jar,此包依赖于类路径下的log4j.xml配置文件。
3、写配置文件:(参考mybatis官方文档)
1)、全局配置文件
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis01"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
2)、配置如何通过Dao操作数据库
<mapper namespace="com.xngao.test.XngaoDao"> :指明是针对那个Dao接口,namespace写的是接口的全路径
<select id="getId" resultType="com.xngao.test.Xngao"> :id指明调用哪个方法,写方法名;resultType返回类型(写类的全路径)
select * from t_xngao where id = #{id} :可以写死,也可以写活
</select>
</mapper>
3)、将2)步骤的配置文件要写入全局配置文件中
<mappers>
<mapper resource="xngaodao.xml"/>
</mappers>
4、测试
获取链接(创建 SqlSessionFactory)—打开链接(获取SqlSession)—获取mapper—执行方法
二、如何写xml时有提示
1、在全局配置文件中复制网址
http://mybatis.org/dtd/mybatis-3-config.dtd
2、选择路径、URI、粘贴网址
三、增删改查
1、查
<select id="getPersonId" resultType="www.xngao.mybatis.PersonBeen">
select * from t_ggg where id = #{id}
</select>
2、改
<update id="update">
update t_ggg
set id=#{id},name=#{name},sex=#{sex},email=#{email}
where id=#{id}
</update>
3、删
<delete id="delete">
delete from t_ggg where id=#{id}
</delete>
4、插入
<insert id="insert" >
insert into t_ggg(id,name,sex,email)
values(#{id},#{name},#{sex},#{email})
</insert>
5、高级查询:动态sql
<select id="getPerson" resultType="www.xngao.mybatis.PersonBeen">
select * from t_ggg where
<if test="id!=null">:test,属性值就是判断条件。
id>#{id} and
</if>
<if test="name!=null">
name like #{name}
</if>
</select>
<select id="getPersonAll" resultType="www.xngao.mybatis.PersonBeen">
select * from t_ggg where id in
<foreach collection="list" item="id_item" separator="," open="(" close=")">
#{id_item}
</foreach>
</select>
<select id="getById" resultMap="ggg">
select * from t_teacher,t_student where t_teacher.id=#{t_teacher.id} and t_teacher.coursenumber=t_student.coursenumber
</select>
四、全局配置文件中的标签
1、properties:引入外部配置文件
创建文件:
username=root
password=123456
jdbcurl=jdbc:mysql://localhost:3306/ggg
driverclass=com.mysql.jdbc.Driver
引用:
- resource:从类路径开始
- url:引用磁盘文件或网络文件
datesourse修改:
- ${}取出属性的值
2、settings:
<settings >
<setting name="mapUnderscoreToCamelCase" value="true"/>:开启自动驼峰命名规则
</settings>
3、typeAliases:为类型或者类起别名,默认别名是类名
<typeAliases>
<typeAlias type="www.xngao.mybatis.PersonBeen" alias="ggg"/>
<package name="www.xngao.mybatis"/>:批量别名,指定包名
</typeAliases>
五、多条件参数查询
1、用索引(底层是map)
2、@param(“id”):命名参数
六、resultMap
自定义结果集,自己定义每一列数据和Javabean的映射规则
- 单表查询 (属性与列名不一样,要起别名(Javabean的属性名))
<select id="getById" resultMap="ggg">:resultMap="ggg",引用后边哪个自定义的resultMap。
select * from t_teacher,t_student where t_teacher.id=#{t_teacher.id} and t_teacher.coursenumber=t_student.coursenumber
</select>
- 多表查询
a、使用级联属性
b、association标签(联合查询)
<resultMap type="www.xngao.mybatis.Teacher" id="ggg">:id,唯一标识,让别名在后面引用。type,为哪个Javabean自定义。
<id property="id" column="id"/>:column="id",指定哪一列是主键。property="id",Javabean的属性。
<result property="name" column="tname"/>
<result property="coursenum" column="coursenumber"/>
<association property="student" javaType="www.xngao.mybatis.Student">
property="student",指定对象属性名。javaType,关联哪个Javabean。
<id property="id" column="id"/>
<result property="snolumn="sname"/>
</association>
</resultMap>