Spring

it2025-02-18  3

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&amp;useSSL=true&amp;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)]
最新回复(0)