Spring学习(二)
八、使用java的方式配置spring
完全不使用spring的xml配置了,全部交给java来做
JavaConfig是spring的一个子项目,在spring4之后就变成了一个核心功能!
//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component
//Configuration代表这是一个配置类,就和我们之前看的beans.xmL
@Configuration
@ComponentScan("com.LH.pojo")
@Import(Myconfig2.class)
public class Myconfig {
//注册一个bean .就相当于我们之前写的一个bean标签1
//这个方法的名字,就相当于bean标签中的id国性
//这个方法的返回值,就相当于bean标签中的cLass属性
@Bean
public User getUser(){
return new User ();//就是要返回注入到bean的对象
}
}
//表示这个类已经被spring接管了
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("猪猪")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Myconfig.class);
User getUser = (User) context.getBean("getUser");
System.out.println(getUser.getName());
}
}
九、代理模式
为什么要学习代理模式?这就是SpringAOP的底层(SpringAOP和SpringMVC)
代理模式:
- 静态代理
- 动态代理
9.1、静态代理
角色分析:
- 抽象角色:一般使用接口或者抽象类解决
- 真实角色:被代理的角色
- 代理角色:代理真实的角色,代理真实的角色后,我们一般会做一些附属的操作
- 客户:访问代理的对象
代码步骤:
1.接口
public interface Rent {
void rent();
}
2.真实角色
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子");
}
}
3.代理角色
public class Proxy {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
host.rent();
SeeHose();
hetong();
}
public void SeeHose(){
System.out.println("中介带你看房");
}
public void hetong(){
System.out.println("签合同");
}
}
4.客户端访问代理
public class Client {
public static void main(String[] args) {
Host host =new Host();
//代理,代理角色一般会有附属操作
Proxy proxy = new Proxy(host);
//你不用找房东,直接找中介租房即可
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关心一些公共的业务
- 公共也交给代理角色!实现业务分工
- 公共业务扩展时更加方便,方便集中管理
缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低
9.2、再理解
简单了解AOP
代码对应08-demo02
9.3、动态代理(多理解)
- 角色和静态代理一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口—jdk动态代理(我们在这使用)
- 基于类—cglib
- java字节码—javasist
需要了解两个类:Proxy:代理,invocationHandler:调用程序处理
public class ProxyInvocationHandler implements InvocationHandler {
//被打理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
//动态代理的实质,就是使用反射机制的实现
Object invoke = method.invoke(target, args);
return invoke;
}
public void log(String msg){
System.out.println("使用了"+ msg+"方法");
}
}
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);//设置要代理的对象
//动态生成要代理的对象
UserService proxy = (UserService) pih.getProxy();
proxy.add();
}
}
动态代理的好处:
- 可以使真实角色的操作更加纯粹,不用去关心一些公共的业务
- 公共也交给代理角色!实现业务分工
- 公共业务扩展时更加方便,方便集中管理
- 一个动态代理类代理的是一个接口,一股就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了
十、AOP
10.1什么是AOP
AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
10.2 Aop在Spring中的作用
提供声明式事务;允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…
- 切面(ASPECT)∶横切关注点被模块化的特殊对象。即,它是一个类。
- 通知(Advice) :切面必须要完成的工作。即,它是类中的一个方法。
- 目标(Target)︰被通知对象。
- 代理(Proxy)︰向目标对象应用通知之后创建的对象。
- 切入点(PointCut)︰切面通知执行的“地点"的定义。
- 连接点(JointPoint) :与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
即Aop在不改变原有代码的情况下,去增加新的功能
10.3 在spring中实现aop
需要导入依赖包
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
方式一:使用spring的API接口【主要是springAPI接口】
方式二:自定义实现aop【切面定义】
方式三:使用注解实现
十一、整合Mybatis
11.1、环境搭建
1.导入Jar包
- junit
- mybatis
- mysql数据库
- spring
- aop
- mybatis-spring【new】
2.编写配置文件
3.测试
11.2、回忆mybatis
1.编写实体类
2.编写核心配置文件
3.编写接口
4.编写Mapper.xml
5.测试
11.3、mybatis-spring
1.User类
package com.LH.pojo;
import lombok.Data;
@Data
public class User {
private int id;
private String name;
private String pwd;
}
2.编写接口UserMapper
package com.LH.mapper;
import com.LH.pojo.User;
import java.util.List;
public interface UserMapper {
public List<User> selectUser();
}
3.UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.LH.mapper.UserMapper">
<select id="selectUser" resultType="user">
select *from mybatis.user
</select>
</mapper>
4.mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.LH.pojo"/>
</typeAliases>
</configuration>
5.spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- DaoSources:使用spring数据源替换Mybatis的配置 c3p0 dbcp druid -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?
useUnicode=true&characterEncoding=UTF-8&useSSL=false&useJDBCCompliantTimezoneShift=true&
useLegacyDatetimeCode=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 绑定mybatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/LH/mapper/*.xml"/>
</bean>
<!-- SqlSessionTemplate:就是我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入 sqlSessionFactory因为没有set方法 -->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userMapper" class="com.LH.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
<bean id="userMapper2" class="com.LH.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
</beans>
6.UserMapperImpl
package com.LH.mapper;
import com.LH.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
import java.util.Map;
public class UserMapperImpl implements UserMapper {
//以前的 操作都是使用sqlSession来操作,现在使用sqlSessionTemplate
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
7.Mytest.java
import com.LH.mapper.UserMapper;
import com.LH.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Mytest {
@Test
public void test() throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
}
8.UserMapperImpl2
package com.LH.mapper;
import com.LH.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser() ;
}
}
十二、声明式事务
1.回顾事务
- 把一组业务当成一个业务来做;要么都成功,要么都失败
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!
- 确保完整性和一致性
事物ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,,结果都不会再被影响,被持久化的写到存储器中!
2.spring的事务管理
- 声明式事务:aop
- 管理事事务
<import resource="spring-dao.xml"/>
<bean id="selectUser" class="com.LH.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给哪些方法配置事务-->
<!-- 配置事务的传播特性:propagation="REQUIRED"默认 -->
<tx:attributes>
<!-- <tx:method name="add" propagation="REQUIRED"/>-->
<!-- <tx:method name="delete"/>-->
<!-- <tx:method name="update"/>-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.LH.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
为什么需要事务?
- 如果不配置事务,可能存在数据提交一致的情况!
- 如果我们不在SPRING中去配置声明式事务,我们就需要在代码中手动配置事务!
utes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.LH.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
为什么需要事务?
- 如果不配置事务,可能存在数据提交一致的情况!
- 如果我们不在SPRING中去配置声明式事务,我们就需要在代码中手动配置事务!
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!