spring
spring是为了解决企业级应用开发的复杂性而创建的,简化开发 。
优点:
-
·Spring是一个开源的免费的框架(容器)!
-
·Spring是一个轻量级的、非入侵式的框架!
-
·控制反转(IOC),面向切面编程(AOP)!
-
支持事务的处理,对框架整合的支持!
总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
1.ioc (控制反转)
1.了解由来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfoBYzSz-1603280894561)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20200601001550528.png)]
1.常规调用,把userDao的实现类绑死了,这里是UserDaoImpl
public class UserServiceImpl implements UserService{
UserDao userDao = new UserDaoImpl();//组合
public void getUserDao() {
userDao.getUser();//调用UserDaoImpl的getUser方法
}
}
2.经过调整,实现控制权的反转
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;//此是userDao是不确定的,由传参人决定其实体类对象
}
public void getUserDao() {
userDao.getUser();//调用UserDao实现类的getUser方法,
// 由传进来的userDao决定,掌控权在传参人手里
}
}
测试类:
public class MyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();//创建UserServiceImpl对象,类型为接口
//etUserDao为UserServiceImpl独有,故需要转型,然后传入参数
((UserServiceImpl)userService).setUserDao(new UserDaoMysqlImpl());
//调用接口方法
userService.getUser();
}
}
总结:
- 之前,程序是主动创建对象!座制权在程序猿手上!
- 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!
这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注的在业务的实现上!这是IOC的原型!
2. ioc本质
使用容器
ClassPathXmlApplicationContext
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();
思考问题?
Hello对象是谁创建的?
hello 对象是由Spring创建的
Hello对象的属性是怎么设置的?
hello 对象的属性是由Spring容器设置的
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转:程序本身不创建对象,而变成被动的接收对象.
依赖注入:就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收.
可以通过newClassPathXmlApplicationContext去浏览一下底层源码.
OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定:对象由Spring 来创建,管理,装配!
2.依赖注入
2.1构造函数的依赖注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
2.1.1构造函数参数类型匹配 (不建议使用)
在前面的场景中,如果您显式指定构造函数参数的类型,则容器可以使用类型匹配和简单类型。type
属性。如下例所示:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
2.1.2构造参数索引
您可以使用index
属性显式指定构造函数参数的索引,如下例所示:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
2.1.2构造函数参数名
还可以使用构造函数参数名称进行值消歧,如下面的示例所示:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
2.2set方式注入【重点】
依赖注入:set注入
- 依赖:bean对象的创建依赖于容器!
- 注入:bean对象中的所有属性,由容器来注入!
3.bean的自动装配
3.1使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持支持注解了!
The introduction of annotation-based configuration raised the question of whether this approach is “better”
than XML.
要使用注解须知:
1.导入约束
2.配置注解的支持
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
3.2使用注解开发
//相当于:<bean id="user" class="com.kuang.pojo.User"></bean>
//@Component 组件
@Component
public class User {
//相当于:<property name="name" value="老王"></property>
@Value("老王")
private String name;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fQbqH50u-1603280894562)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20200602004625592.png)]
小结:xml与注解:
- xml更加万能,适用于任何场合!维护更加简单方便
- 注解 不是自己类使用不了,维护相对复杂!
xml与注解最佳实践:
- xml用来管理bean;
- 注解只负责完成属性的注入;
- 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个下的注解就会生效-->
<context:component-scan base-package="com.kuang.pojo"/>
<context:annotation-config/>
4.代理
1.静态代理
2.动态代理
//通用代理类
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 {
Object result = method.invoke(target, args);
return result;
}
}
接口:
public interface Rent {
void rent();
}
真实类:
public class Host implements Rent{
public void rent() {
System.out.println("出租房子!");
}
}
客户类+main方法:
public class Client {
public static void main(String[] args) {
//真实对象
Rent rent = new Host();
//代理对象,不存在
ProxyInvocationHandler handler = new ProxyInvocationHandler();
handler.setTarget(rent);//设置代理对象,传入真实对象
//动态生成代理类
Rent proxy = (Rent)handler.getProxy();
//调用其方法
proxy.rent();
}
}
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
动态代理的好处:
- 可以使真实角色的操作更加纯粹!不用去关注一些公共的业
- 公共也就就交给代理角色!实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
5.AOP
1.什么是aop
2.aop在spring中的作用
3.使用spring实现aop
【重点】使用AOP织入,需要导入一个依赖包!
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
方式一:使用spring的API接口【主要springAPI接口实现】
方式二:自定义来实现AOP【主要是切面定义】
方式三:使用注解实现!
切入点表达式:
作用:对哪个类里面的哪个方法进行增强
语法结构:
execution([权限修饰符][返回值类型][类全路径][方法名称]([参数列表]))
例如:对com.kuang.dao.BookDao类里面的add进行增强
返回值类型 可以不写,权限修饰符可以用 * 表示所有
execution(* com.kuang.dao.BookDao.add(..))
如果式该类中的所有方法都增强的话 方法处用 * 代替,表示所有。
6.整合mybatis
1.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核心配置文件-->
<configuration>
<!--设置别名-->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
</configuration>
2.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--专注于操作数据库-->
<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&useSSL=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--使用 SqlSessionFactoryBean来创建 SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--绑定Mybatis配置文件,可以绑定也可以不绑定,建议绑定-->
<property name="configLocation" value="mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/kuang/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate就是我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为SqlSessionTemplate没有构造方法-->
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
</beans>
3.applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession" />
</bean>
</beans>
4.UserMapperImpl
//这个类似乎就是以前的工具类MybatisDao,只不过现在由spring接管
public class UserMapperImpl implements UserMapper{
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
5.MyTest
public class MyTest {
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapperImpl.class);
List<User> users = userMapper.selectUser();
for (User user : users) {
System.out.println(user);
}
}
}
7.声明式事务
1.回顾事务:
-
把一组业务当成一个业务来做,要么都成功,要么都失败!
-
事务在项目中,十分重要,涉及数据的一致性问题,不能马虎!
-
确保问政性和一致性;
事务ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中!
2.spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
思考:
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况;
- 如果我们不在spring中配置声明式事务,我们就要在代码中手动配置事务!
- 事务在项目中十分重要,涉及数据的一致性和完整性问题,不容马虎!
ectUser();
for (User user : users) {
System.out.println(user);
}
}
}
## 7.声明式事务
### 1.回顾事务:
- 把一组业务当成一个业务来做,要么都成功,要么都失败!
- 事务在项目中,十分重要,涉及数据的一致性问题,不能马虎!
- 确保问政性和一致性;
事务ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写到存储器中!
### 2.spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
思考:
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况;
- 如果我们不在spring中配置声明式事务,我们就要在代码中手动配置事务!
- 事务在项目中十分重要,涉及数据的一致性和完整性问题,不容马虎!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5k7gIqo6-1603280894562)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20200604122958318.png)]