轻量级、非入侵式的框架
免费开源框架(容器)
控制反转,,面向切面
支持事务处理,对框架的整合
Spring Boot
快速开发脚手架
约定大于配置
Spring Cloud
SpringCloud基于Springboot实现
UserDao接口
UserDaoImpl实现类
UserService业务接口
UserService业务实现类
用户的需求会导致我们修改源代码,破坏程序的完整性;
使用set注入后,程序不再具有主动性
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
降低耦合性
package com.ming.pojo;
/**
* @Author:weiming
* @Date:2020/7/12 11:39
*/
public class Hello {
private String Name;
public void setName(String name) {
Name = name;
}
public String getName() {
return Name;
}
@Override
public String toString() {
return "Hello{" +
"Name='" + Name + '\'' +
'}';
}
}
<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="hello" class="com.ming.pojo.Hello">
<property name="Name" value="spring"/>
bean>
beans>
public class mytest {
public static void main(String[] args) {
//获取spring上下文
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvOzorv3-1595255353978)(C:\Users\zwm\AppData\Roaming\Typora\typora-user-images\image-20200712115913999.png)]
控制:Spring帮我们管理和创建的对象
反转:程序本身不创建对象,而被动的变成接收对象
依赖注入:利用set方法注入(体会ioc推导中的set作用),如果删掉set方法会报错
控制反转
采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。
package com.ming.pojo;
/**
* @Author:weiming
* @Date:2020/7/13 10:30
*/
public class User {
private String name;
public User (){
System.out.println("User的无参构造");
}
// public User(String s) {
// }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show (){
System.out.println("name"+name);
}
}
<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="user" class="com.ming.pojo.User">
<property name="Name" value="ming"/>
bean>
beans>
public class MyTest {
public static void main(String[] args) {
//new User();
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
User user = (User) applicationContext.getBean("user");
user.show();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EsXVrYae-1595255353981)(C:\Users\zwm\AppData\Roaming\Typora\typora-user-images\image-20200713105340198.png)]
2.使用有参构造,下标赋值
<!--下标赋值-->
<bean id="user" class="com.ming.pojo.User">
<constructor-arg index="0" value="ming"/>
<constructor-arg index="1" value="20"/>
</bean>
3.类型赋值,局限性大,不推荐
<bean id="user" class="com.ming.pojo.User">
<constructor-arg type="java.lang.String" value="ming"/>
<constructor-arg type="int" value="20"/>
</bean>
4.对应名称赋值,最常用
<!--对应名称赋值,最常用-->
<bean id="user" class="com.ming.pojo.User">
<constructor-arg name="name" value="weiming"/>
<constructor-arg name="Age" value=" 20"/>
</bean>
总结,在配置文件加载的时候,容器(ApplicationContext)就初始化了管理的对象
<alias name="user" alias="userName"/>
可以用别名取bean
<!--id是bean的唯一标识,也就是相当于对象名
class :包名+类型
name:也是别名,可以取多个别名
-->
<bean id="userT" class="com.ming.pojo.UserT" name="userT2 userT3,userT4;userT5">
</bean>
这个import,一般用于团队开发,可以将多个配置文件合并为一个。可以用import所有的bean.xml,使用的时候直接用总的配置即可
ApplicationContext.xml
<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">
<import resource="bean.xml"/>
<import resource="bean1.xml"/>
beans>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywqzPHsD-1595255353983)(C:\Users\zwm\AppData\Roaming\Typora\typora-user-images\image-20200713132608891.png)]
三种构造方式之一
构造器注入,Set方式注入(重点),拓展方式注入
依赖注入:set注入
依赖:bean对象依赖于容器
注入:bean对象中的所有属性,由容器来注入
【环境搭建】
package com.ming.pojo;
/**
* @Author:weiming
* @Date:2020/7/13 14:28
*/
public class Address {
private String address;
}
package com.ming.pojo;
import java.util.*;
/**
* @Author:weiming
* @Date:2020/7/13 14:28
*/
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List<String> getHobbbys() {
return hobbbys;
}
public void setHobbbys(List<String> hobbbys) {
this.hobbbys = hobbbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbbys=" + hobbbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
p-命名空间注入 对应set注入
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.ming.pojo" p:name="ming" p:age="18"/>
</beans>
c-命名空间 对应构造器注入(有参)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.ming.pojo" c:name="ming" c:age="18"/>
</beans>
Scope | Description |
---|---|
singleton(单例) | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype(原型模式 | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
单例模式(默认)
<bean id="address" class="com.ming.pojo.Address" scope="singleton"/>
每次取得都是同一个对象
原型模式
<bean id="address" class="com.ming.pojo.Address" scope="prototype"/>
每次都创建一个对象
Spring自动在上下文寻找,并且自动给Bean配置属性
<bean id="cat" class="com.ming.pojo.Cat"/>
<bean id="dog" class="com.ming.pojo.Dog"/>
<bean id="person" class="com.ming.pojo.Person" autowire="byName">
<property name="name" value="ming"/>
bean>
<bean id="cat" class="com.ming.pojo.Cat"/>
<bean id="dog" class="com.ming.pojo.Dog"/>
<bean id="person" class="com.ming.pojo.Person" autowire="byName">
<property name="name" value="ming"/>
bean>
jdk1.5支持注解,spring2.5支持注解
注解需知
导入约束
配置注解支持
<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>
@Autowired(required = false)允许为空
实际是byType的模式,如果type相同再按照byName寻找
@Qualifier(“dog123”) 当类型不唯一时
@Qualifier("dog123")
private Dog dog;
<bean id="dog123" class="com.ming.pojo.Dog"/>
<bean id="dog222" class="com.ming.pojo.Dog"/>
当类型重复时,为他指定一个默认的id进行装配
注解开发需要aop包,需要context约束
<context:component-scan base-package="com.ming.pojo"/>
在类上使用@Component 说明这个类被Spring管理了
//等价于
@Component
public class User {
private String Name;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
package com.ming.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Author:weiming
* @Date:2020/7/15 15:30
*/
//等价于
@Component
public class User {
//等价于
@Value("weiming")
private String Name;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
如果赋值复杂的类型,建议还是使配置文件
在springMVC里面有三层架构
controller【@Controller】
service【@Service】
dao【@Repository】
注解的功能都是一样的,将类注册到容器中,装配Bean
@Configuration
public class myConfig {
@Bean
public User getUser(){
return new User();
}
}
public class Mytest {
@Test
public void test1(){
ApplicationContext context = new AnnotationConfigApplicationContext(myConfig.class);
User user = context.getBean("getUser",User.class);
System.out.println(user.getName());
}
}
在配置类中的方法名相当于xml中配置的name。
分类
举例,房东把房子钥匙给中介,租房的人找中介看房,中介实现租房的接口方法
接口:租房
//租房的接口
public interface Rent {
public void rent();
}
真实角色:房东
//房东
public class Host implements Rent{
public void rent() {
System.out.println("出租房屋");
}
}
代理角色:中介
public class Proxy implements Rent{
private Host host;
public Proxy(Host host) {
this.host = host;
}
public Proxy(){
}
public void rent() {
host.rent();
}
}
客户端访问代理角色
//客户租房
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理模式的好处
缺点
==开闭原则:==当业务功能发生变更的时候,可以不去直接修改软件实体的源代码情况下,可以拓展模块的功能,使其满足新需求
理解:感觉就是,不是直接调用业务代码,而是在原来业务代码的基础上面,多封装了一层调用层,然后在调用层拓展公共的功能。是和开闭原则的实现
AOP
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-80ohJLZS-1595255353986)(C:\Users\zwm\AppData\Roaming\Typora\typora-user-images\image-20200716183444376.png)]
动态代理是动态实现的,不是直接写好的
动态代理的分类:基于接口的,基于类的
基于接口的—jdk实现
基于类的–cglib
基于java字节码的:javasist
//自动生成动态代理
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理类
public Object getProxy(){
//参数:获取类的位置,代理的接口
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
//处理代理的实例,并且返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质是通过反射实现的
Object result = method.invoke(rent, args);
return result;
}
}
public class Client {
public static void main(String[] args) {
Host host = new Host();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host);
Rent rent = (Rent) pih.getProxy();
rent.rent();
}
}
导入依赖
<dependencies>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
dependencies>
方式一 :Spring方式,原生API
<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
http://www.springframework.org/schema/aop/spring-aop.xsd"
>
<bean id="userService" class="com.ming.service.UserServiceImpl"/>
<bean id="log" class="com.ming.Log.Log"/>
<bean id="afterLog" class="com.ming.Log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ming.service.UserServiceImpl.*(..))">aop:pointcut>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
aop:config>
beans>
方式二:
自定义切面类
package com.ming.diy;
/**
* @Author:weiming
* @Date:2020/7/17 11:58
*/
public class diyCutPoint {
public void before(){
System.out.println("=========在之前=========");
}
public void after(){
System.out.println("=========在之后=========");
}
}
<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
http://www.springframework.org/schema/aop/spring-aop.xsd"
>
<bean id="userService" class="com.ming.service.UserServiceImpl"/>
<bean id="log" class="com.ming.Log.Log"/>
<bean id="afterLog" class="com.ming.Log.AfterLog"/>
<bean id="diy" class="com.ming.diy.diyCutPoint"/>
<aop:config >
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.ming.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
aop:aspect>
aop:config>
beans>
方法三:注解
@Aspect
public class AnnotationPointCut {
//切入点
@Before("execution(* com.ming.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("=========在之前=========");
}
@After("execution(* com.ming.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("=========在之后=========");
}
}
<bean id="annotationPointCut" class="com.ming.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy />
junit
mysql
mybatis
aop植入
mybatis-spring
spring相关的
相关依赖
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version> 4.12version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version> 8.0.21version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version> 3.5.4version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version> 5.1.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version> 1.8.11version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.2version>
dependency>
dependencies>
spring-mybatis.xml
<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="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/jdbcdemo?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatisConfig.xml"/>
<property name="mapperLocations" value="classpath:com/ming/mapper/*.xml"/>
bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
bean>
<bean id="userMapper" class="com.ming.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
bean>
beans>
UserMapperImpl.java
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
/**
* @Author:weiming
* @Date:2020/7/18 17:20
*/
public class UserMapperImpl implements UserMapper {
//我们的所有的操作,都使用Sqlsession来执行在原来,现在使用SqlsessionTemplate
public SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<mybatis> selectUser() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
return userMapper.selectUser();
}
}
原来mybatis.xml的配置最终精简为
<configuration>
<typeAliases>
<package name="com.ming.pojo"/>
typeAliases>
configuration>
精简,省略SqlsessionTemplate,继承了sqlsessionDaoSupport这样就不用去私有化sqlsessionfactory(参考UserMapperImpl的操作)
/**
* @Author:weiming
* @Date:2020/7/18 19:09
*
*
* 继承了sqlsessionDaoSupport这样就不用去私有化sqlsessionfactory(参考UserMapperImpl的操作)
*/
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
public List<mybatis> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
在xml配置中注入SqlsessionTemplate
<bean id="userMapper2" class="com.ming.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>
要么都成功,要么都失败
事务ACID
http://mybatis.org/spring/zh/transactions.html
申明式事务(aop)
要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager
对象:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
bean>
配置事务通知
<tx:advice id="advise" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="del"/>
<tx:method name="update"/>
<tx:method name="query"/>
<tx:method name="*"/>
tx:attributes>
tx:advice>
propagation
一、在声明式的事务处理中,要配置一个切面,其中就用到了propagation,表示打算对这些方法怎么使用事务,是用还是不用,其中propagation有七种配置,REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。默认是REQUIRED。
二、Spring中七种Propagation类的事务属性详解:
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
三、注意.
这个配置将影响数据存储,必须根据情况选择。
————————————————
版权声明:本文为CSDN博主「sayok_why」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sayoko06/article/details/79164858
将事务织入,通过aop切入
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ming.mapper.*.*(..))"/>
<aop:advisor advice-ref="advise" pointcut-ref="pointcut">aop:advisor>
aop:config>
完整配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
bean>
<tx:advice id="advise" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="del"/>
<tx:method name="update"/>
<tx:method name="query"/>
<tx:method name="*"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ming.mapper.*.*(..))"/>
<aop:advisor advice-ref="advise" pointcut-ref="pointcut">aop:advisor>
aop:config>
事务可以解决数据一致性的问题
请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sayoko06/article/details/79164858
将事务织入,通过aop切入
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ming.mapper.*.*(..))"/>
<aop:advisor advice-ref="advise" pointcut-ref="pointcut">aop:advisor>
aop:config>
完整配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
bean>
<tx:advice id="advise" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="del"/>
<tx:method name="update"/>
<tx:method name="query"/>
<tx:method name="*"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.ming.mapper.*.*(..))"/>
<aop:advisor advice-ref="advise" pointcut-ref="pointcut">aop:advisor>
aop:config>
事务可以解决数据一致性的问题