- Spring学习
- 1、Spring组成
- 2、IOC理论推导
- 3、IOC创建对象的方式
- 3.1使用无参构造创建,默认
- 3.2使用有参构造创建
- 4、Spring配置
- 4.1别名
- 4.2Bean的配置
- 5、依赖注入
- 5.1构造器注入
- 5.2Set方式注入【重点】
- 5.3拓展方式注入
- 5.4bean的作用域
- 6、Bean的自动装配
- 6.1、测试
- 6.2、ByName自动装配
- 6.3、ByType自动装配
- 6.4、 使用注解实现自动装配
- 7、使用注解开发
- 注解
- 8、完全使用Java的方式配置Spring
- 9、代理模式
- 9.1、静态代理
- 9.2、动态代理
- 10、AOP
- 10.1、AOP介绍
- 10.2、使用Spring实现AOP
- 11、整合Mybatis
- 11.1、回忆Mybatis
- 12、声明式事务
- 1、回顾事务
- SpringBoot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发单个微服务
- 约定大于配置
- SpringCloud
- SpringCloud是基于SpringBoot实现的
大多是公司都在使用SpringBoot进行快速开发,学习Springboot的前提,就是完全掌握Spring以及SpringMVC,其承上启下的作用
弊端:发展太久了,违背了之前的理念,配置十分繁琐“配置地狱”
2、IOC理论推导对象由Spring来创建,管理,装配
IOC(控制反转)的本质:是一种设计思想,将对象的创建交给了第三方,完全由程序自己控制:即获得依赖对象的方式反转了
是Spring框架的核心内容
Spring在容器初始化时,先读取配置文件,根据配置文件或元数据创建与组织对象放入容器中,程序使用时再从容器中取出需要的对象*控制反转是一种通过描述(XML或注解)并通过第三方去产生或获取特定对象的方式,在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入
-
UserDao接口
-
UserDaoImpl实现类
-
UserService业务接口
-
UserServiceImpl业务实现类
需要根据用户修改源代码,会破坏程序的完整性,代价昂贵
通过使用set接口实现:
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
程序不在具有主动性,而是变成被动接受对象
从本质上解决了问题,不用再去管理对象的创建,系统的耦合性大大降低,可以更加专注的在业务的实现上,这就是IOC的原型
3、IOC创建对象的方式 3.1使用无参构造创建,默认 3.2使用有参构造创建-
下标赋值
<bean id="user" class="com.zhai.pojo.User"> <constructor-arg index="0" value="zhaichenji"/> bean>
-
通过类型创建
<bean id="user" class="com.zhai.pojo.User"> <constructor-arg type="java.lang.String" value="zhaichen"/> bean>
-
通过参数名来设置
<bean id="user" class="com.zhai.pojo.User"> <constructor-arg name="name" value="zhai"/> bean>
在配置文件加载的时候,容器中的对象就已经初始化了
4、Spring配置 4.1别名
<alias name="user" alias="userNew"/>
4.2Bean的配置
<bean id="userT" class="com.zhai.pojo.UserT" name="user2 u2">
<property name="name" value="zhaichenji"/>
bean>
-
import
一般用于团队开发使用,可以将多个配置文件,导入合成一个
假设现在项目中有多个人开发,这三个人负责不同的类,不同的类需要注册在不同的bean中,可以利用import将所有人的合并成一个总的。
-
applicationContext.xml
<import resource="beans.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/>
-
-
依赖注入:set注入
-
依赖:bean对象的创建依赖容器
-
依赖:bean对象中的所有属性,有容器来注入
-
【环境搭建】
-
复杂类型
private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }
-
真实测试对象
private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info;
-
beans.xml
<bean id="student" class="com.zhai.pojo.Student"> <property name="name" value="小"/> bean>
-
测试类
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student =(Student) context.getBean("student"); System.out.println(student.getAddress()); }
-
完善注入信息
<bean id="address" class="com.zhai.pojo.Address"> <property name="address" value="宁夏"/> bean> <bean id="student" class="com.zhai.pojo.Student"> <property name="name" value="小"/> <property name="address" ref="address"/> <property name="books"> <array> <value>红楼梦value> <value>数据结构value> <value>大数据value> <value>人工智能value> array> property> <property name="hobbys"> <list> <value>吃value> <value>玩value> <value>睡value> list> property> <property name="card"> <map> <entry key="身份z" value="142536633320125582"/> <entry key="yhk" value="6969665542201236875"/> map> property> <property name="games"> <set> <value>LOLvalue> <value>DNFvalue> <value>CSGOvalue> set> property> <property name="wife"> <null/> property> <property name="info"> <props> <prop key="学号">12018242282prop> <prop key="性别">男prop> <prop key="专业">软件工程prop> props> property> bean>
可以使用p命名空间和c命名空间进行属性注入
官方解释:
使用:
<bean id="user" class="com.zhai.pojo.User" p:name="小明" p:age="18"/>
<bean id="user2" class="com.zhai.pojo.User" c:name="小明" c:age="18"/>
测试:
@Test
public void test2(){
//p命名空间
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
@Test
public void test3(){
//c命名空间
ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user2", User.class);
System.out.println(user);
}
注意点:p命名空间和c命名空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
5.4bean的作用域
-
单例模式(Spring默认机制)
<bean id="user2" class="com.zhai.pojo.User" c:name="18" c:age="小明" scope="singleton"/>
-
原型模式:每次容器中get的时候,都会产生一个新对象
<bean id="user2" class="com.zhai.pojo.User" c:name="18" c:age="小明" scope="prototype"/>
-
其余的request、session、application只能在web开发中使用到!
- 自动装配:是Spring满足Bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给Bean装配属性
三种装配方式:
- 在xml中显示的配置
- 在java中配置
- 隐式的自动装配【重要】
- 环境搭建:一个人有两个宠物
<bean id="people" class="com.zhai.pojo.People" autowire="byName">
<property name="name" value="小明"/>
bean>
6.3、ByType自动装配
<bean id="people" class="com.zhai.pojo.People" autowire="byType">
<property name="name" value="小明"/>
bean>
小结:
- byName时,需保证所有bean的id唯一,且这个bean需要和自动注入的属性set方法一致
- byType时,需保证所有bean的class唯一,且这个bean需要和自动注入的属性类型一致
Spring从2.5开始支持注解
“基于注解的配置的引入提出了一个问题,即这种方法是否比 XML“更好”。简短的答案是“取决于情况”。”
使用注解须知:
-
导入约束:context约束
-
配置注解的支持context:annotation-config/【重要】
<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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> beans>
@Autowired:
1、直接在属性上使用即可,也可以在set方法上使用**
2、使用@Autowired可以不写set方法,前提是自动装配属性在IOC中(Spring中)存在,且符合名字byName
注:
@Nullable 被次注解标记的字段,值可以为Null
//如果显示required 的属性为false,则该值可以为null public @interface Autowired { boolean required() default true; }
测试代码:
public class People { //如果显示required 的属性为false,则该值可以为null @Autowired(required = false) private Cat cat; @Autowired private Dog dog; private String name; }
如果@Autowired自动装配的环境比较复杂,无法通过一个注解完成时,则可以使用注解【@Qualifier(value = “xxx”)】配置@Autowired的使用,指定一个惟一的bean对象的注入
public class People { @Autowired @Qualifier(value = "cat111") private Cat cat; @Autowired @Qualifier(value = "dog222") private Dog dog; }
@Resource注解
public class People { @Resource(name = "cat2") private Cat cat; @Resource private Dog dog; private String name; }
小结:
@Resource和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过buType的方式实现,而且必须要求这个对象存在【常用】
- @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到,就会报错,
- 执行顺序不同:
- @Autowired通过buType的方式实现,@Resource默认通过byName的方式实现
在Spring4之后,使用注解开发,必须导入AOP的包
使用注解需要导入context约束,增加注解的支持
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
注解
- @Autowired:通过名字自动装配
- 如果@Autowired不能唯一的自动装配,则需要使用@Qualifier(value = “xxx”)
- @Nullable:被此标记标记的属性,可以为null
- @Resource:通过名字自动装配,其次是类型
- @Component:放在类上,说明这个类被Spring管理了,就是bean
-
bean
-
属性如何注入
@Component public class User { //通过注解赋值 //相当于
@Value("小明") public String name; } -
衍生的注解
@Component有几个衍生注解,web开发中,按照MVC三层架构:
- dao【@Repository】
- service【@Service】
- controller【@Controller】
四个注解功能一样,都是将类注册到Spring容器中装配bean
-
自动装配置
- @Autowired:通过名字自动装配 - 如果@Autowired不能唯一的自动装配,则需要使用@Qualifier(value = "xxx") - @Nullable:被此标记标记的属性,可以为null - @Resource:通过名字自动装配,其次是类型
-
作用域
@Component //作用域 @Scope("prototype") public class User { //通过注解赋值 //相当于
@Value("小明") public String name; } -
小结
xml与注解
- xml万能,适用于任何场合,维护简单方便
- 注解不是自己的类使用不了,维护相对复杂
最佳实践:
- xml管理bean
- 注解完成属性注入
- 在使用过程中,只需要注意一个问题,必须让注解生效,需要开启注解支持
<context:component-scan base-package="com.zhai"/> <context:annotation-config/>
要完全不使用Spring的xml配置,全权叫个Java来做
JavaConfig是Spring的一个子项目,在Spring4之后,成为了核心功能
实体类
//这个注解的意思就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
private String name;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
//属性注入值
@Value("小明")
public void setName(String name) {
this.name = name;
}
}
测试类
@Test
public void Test1() {
//如果完全使用配置类方式,就只能通过AnnotationConfigApplicationContext上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(ZhaiConfig.class);
User getUser = context.getBean("user", User.class);
System.out.println(getUser.getName());
}
这种纯Java的配置方式,在SpringBoot中,随处可见
9、代理模式为什么学习代理模式?
- 因为这是SpringAOP的底层【SpringAOP 和 SpringMVC】
代理模式分类:
- 静态代理
- 动态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,会做一些附属 *** 作
- 客户:访问代理对象的人
代码步骤:
-
接口
//租房的接口 public interface Rent { public void rent(); }
-
真实角色
//房东 public class Host implements Rent{ @Override public void rent() { System.out.println("房东要出租房子"); } }
-
代理角色
public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } public void rent() { host.rent(); seeHouse(); hetong(); fare(); } //看房 public void seeHouse(){ System.out.println("中介带你看房"); } //收中介费用 public void fare(){ System.out.println("收中介费"); } //签租赁合同 public void hetong(){ System.out.println("签租赁合同"); } }
-
客户端访问代理角色
public class Client { public static void main(String[] args) { //房东要出租房子 Host host = new Host(); //代理,中介帮房东出租房子,但是代理角色一般会与一些附属 *** 作 Proxy proxy = new Proxy(host); //你不用面对房东,直接找中介租房子 proxy.rent(); } }
代理模式好处:
- 可以是真实角色的 *** 作更加纯粹,不用去关注一些公共的业务
- 公共业务就交给了代理角色去做,实现业务分工
- 公共业务发生扩展的时候,方便集中管理
代理模式缺点:
- 一个真实角色就会产生一个代理角色,代码量翻倍,开发效率会变低
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是直接写出来的
- 动态代理分为两大类:
- 基于接口的动态代理
- JDK动态代理【使用】
- 基于类的动态代理
- cglib
- java字节码实现:javassist
- 基于接口的动态代理
需要两个类:
- Proxy:代理
- InvocationHandler:调用处理程序
动态代理的好处:
- 可以是真实角色的 *** 作更加纯粹,不用去关注一些公共的业务
- 公共业务就交给了代理角色去做,实现业务分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应一类业务
- 一个动态代理类可以代表多个类,只要实现了同一个接口即可
导入AOP依赖包
<dependencies>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
dependencies>
方式一:使用Spring的API接口【主要是SpringAPI接口实现】
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.zhai.service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
aop:config>
方式二:自定义来实现AOP【主要是切面】
<bean id="diy" class="com.zhai.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.zhai.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
aop:aspect>
aop:config>
方式三:使用注解实现
<bean id="annotationPointCut" class="com.zhai.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy/>
11、整合Mybatis
步骤:
-
导入相关jar包
- junit
- myBatis
- mysql数据库
- spring相关
- aop织入
- mybaits-spring【new】
-
编写配置文件
-
测试
- 编写实体类
- 编写核心配置文件
- 编写接口
- 编写Mapper.xml
- 测试
- 要么都成功,要么都失败
- 事务在项目开发中,十分重要,涉及到数据的一致性问题,不能马虎
- 确保完整性和一致性
事务的ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能 *** 作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写入到存储器中
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)