spring笔记
spring配置
别名
<bean id="user" class="com.zeng.pojo.User">
<property name="name" value="AAAAAA"/>
</bean>
<!--别名-->
<alias name="user" alias="ladjfa"/>
Bean配置
<!--
id:bean的唯一标识符,相当于对象名
calss:bean对象所对应的全限定名:包名+类型
name:也是别名,而且name可以同时取多个别名
-->
<bean id="user" class="com.zeng.pojo.User" name="user2 user5,user3;user4">
<property name="name" value="AAAAAA"/>
</bean>
import
可以将多个配置文件,导入合并成一个
<import resource="beans.xml"/>
依赖注入
构造器注入
Set方式注入
- 依赖注入:Set注入!
依赖:bean对象的创建依赖于容器
注入:bean对象中的属性,由容器注入
<bean id="address" class="com.zeng.pojo.Address">
<property name="address" value="中国湖北襄阳"/>
</bean>
<bean id="student" class="com.zeng.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="abc"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>三国演义</value>
<value>水浒传</value>
<value>西游记</value>
</array>
</property>
<!--list-->
<property name="hobbys">
<list>
<value>抽烟</value>
<value>喝酒</value>
<value>烫头</value>
</list>
</property>
<!--map-->
<property name="card">
<map>
<entry key="身份证" value="1233211"/>
<entry key="银行卡" value="001233211"/>
</map>
</property>
<!--set-->
<property name="games">
<set>
<value>nba2k</value>
<value>lol</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--配置文件类型-->
<property name="prop">
<props>
<prop key="driver">22355@ss</prop>
<prop key="url">www.baidu.com</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
拓展方式注入
可以使用c和p命名空间进行注入
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.zeng.pojo.User" p:name="小小飞" p:age="23" />
<!--c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="com.zeng.pojo.User" c:name="大大飞" c:age="22" />
测试
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
// User bean = context.getBean(User.class);
User user = context.getBean("user",User.class);
User user1 = context.getBean("user2",User.class);
System.out.println(user.toString());
System.out.println(user1.toString());
}
注意点:c和p命名空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
Bean作用域
- 单例模式(spring默认机制):scope="singleton"
<bean id="user2" class="com.zeng.pojo.User" c:name="大大飞" c:age="22" scope="singleton"/>
- 原型模式:每次从容器中get对象的时候,都会产生一个新的对象:scope="prototype"
<bean id="user2" class="com.zeng.pojo.User" c:name="大大飞" c:age="22" scope="prototype"/>
Bean的自动装配
- 自动装配是Spring满足Bean依赖的一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
在spring中有三种装配方式:
- 在xml中显示的配置
- 在java中显示配置
- 隐式的自动装配bean
byName自动装配
<!--
byName:会自动在容器上下文中查找和自己对象set方法后面值对应的beanid
-->
<bean id="people" class="com.zeng.pojo.People" autowire="byName">
<property name="name" value="小小飞"/>
</bean>
byType自动装配
<!--
byType:会自动在容器上下文中查找和自己对象属性类型相同的bean!
-->
<bean id="people" class="com.zeng.pojo.People" autowire="byType">
<property name="name" value="小小飞"/>
</bean>
小结:
- byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
- byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
使用注解实现自动装配
要使用注解需修改配置:
- 导入约束:context约束
- 配置注解的支持: context:annotation-config/
<?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>
@Autowired
直接在属性上使用即可!可以在set方式上使用!
使用Autowired可以不用编写set方法,前提是这个自动装配的属性在ioc容器中存在,且符合名字byName
@Nullable 字段标记了这个注解,说名这个字段可以为null
public @interface Autowired{
boolean required() default true;
}
测试代码:
public class People {
private String name;
//如果显示定义了 Autowired的 required属性为fa1se,说明这个对象可以为nu11,否则不允许为空
@Autowired(required = false)
private Dog dog;
@Autowired
private Cat cat;
}
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(value="xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!
public class People {
private String name;
@Autowired
@Qualifier(value = "dog222")
private Dog dog;
@Autowired
private Cat cat;
}
@Resource
public class People {
private String name;
@Resource(name = "dog2")
private Dog dog;
@Resource
private Cat cat;
小结:
@Autowired 和 @Resource 的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 通过byType的方式实现,而且必须要求这个对象存在
- @Resource 默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!
- @Nullable:字段标记了这个注解,说明这个字段可以为null;
- @Component:组件,放在类上,说明这个类被spring管理了,就是bean!
- 执行顺序不同: @Autowired 通过byType的方式实现,@Resource 默认通过byName的方式实现
使用注解开发
- bean
- 属性如何注入
@Component // 等价于 <bean id="user" class="com.zeng.pojo.User" />
public class User {
@Value("大大飞") // 相当于<property name="name" value"大大飞" />
public String name;
}
- 衍生的注解
@Component:有几个衍生的注解,在web开发中,会按照mvc三层架构分层!
- dao:【@Repository】
- service:【@Service】
- controller:【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到spring中,装备bean
- 自动装配
- 作用域
- 小结
xml与注解:
xml适用于任何场合!维护简单方便!
注解只能维护自己的类,维护相对复杂!
xml与注解最佳组合:
xml用来管理bean!
注解只负责完成属性的注入!
在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持!
使用java的方式配置spring
JavaConfig是Spring的一个子项目,在spring4之后,成为了一个核心功能!
实体类:
@Component // 说明这个类被spring接管了,注册到了容器中
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 + '\'' +
'}';
}
}
配置类:
@Configuration // spring容器托管,注册到容器中,代表这是一个配置类,和之前的beans.xml
@ComponentScan("com.zeng.pojo")
public class Config {
// 注册一个bean,就相当于我们之前写的一个bean标签
// 这个方法名字,就相当于bean标签中的id属性
// 这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User getUser(){
return new User(); // 返回要注入到bean的对象!
}
}
测试:
public class MyTest {
@Test
public void test(){
// 如果完全使用了配置类方式去做,就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = (User) context.getBean("getUser");
System.out.println(user.getName());
}
}
代理模式
SpringAop的底层就是代理模式
代理模式分类:
- 静态代理
- 动态代理
静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽奖类来解决
- 真是角色:被代理的角色
- 代理角色:代理真是角色,代理真是角色后,一般会有一些附属操作
- 客户:访问代理对象的人
代码步骤:
- 接口
- 真是角色
- 代理角色
- 客户端访问
代理模式的好处:
- 可以使真是角色的操作功能更单一,不用去关注一些公共的业务!
- 公共业务就交给了代理角色,实现了业务的分工
- 公共的业务发生扩展的时候,方便集中管理
缺点: - 一个真实角色就会产生一个代理角色,代码量会增加
动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是直接写好的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:Jdk动态代理
- 基于类:cglib
- java字节码实现:javaasist
动态代理的好处:
- 可以使真是角色的操作功能更单一,不用去关注一些公共的业务!
- 公共业务就交给了代理角色,实现了业务的分工
- 公共的业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理可以代理多个类,只要是实现了同一个接口即可
AOP
使用aop需要先导入一个依赖包
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
三种方式
<!--注册bean-->
<bean id="userService" class="com.zeng.service.UserServiceImpl"/>
<bean id="log" class="com.zeng.log.Log"/>
<bean id="afterLog" class="com.zeng.log.AfterLog"/>
<!-- 方式一:使用原生Spring Api接口-->
<!--配置aop,需要导入aop的约束-->
<!-- <aop:config>-->
<!--切入点:expression:表达式,execution(要执行的位置 * * * * *)-->
<!-- <aop:pointcut id="pointcut" expression="execution(* com.zeng.service.UserServiceImpl.*(..))"/>-->
<!--执行环绕增加-->
<!-- <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
<!-- <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>-->
<!-- </aop:config>-->
<!--方式二:自定义类-->
<!-- <bean id="div" class="com.zeng.div.Diy"/>-->
<!-- <aop:config>-->
<!--自定义切面,ref 要引用的类-->
<!-- <aop:aspect ref="div">-->
<!--切入点-->
<!-- <aop:pointcut id="point" expression="execution(* com.zeng.service.UserServiceImpl.*(..))"/>-->
<!--通知-->
<!-- <aop:before method="befor" pointcut-ref="point"/>/-->
<!-- <aop:after method="after" pointcut-ref="point"/>-->
<!-- </aop:aspect>-->
<!-- </aop:config>-->
<!-- 方法三:使用注解-->
<bean id="annotationPointCut" class="com.zeng.div.AnnotationPointCut"/>
<!-- 开启注解支持-->
<aop:aspectj-autoproxy/>
整合Mybatis
步骤:
- 导入jar包
- junit
- mybaits
- mysql数据库
- spring相关的
- aop支持
- mybatis-spring
- 编写配置文件
- 测试
声明式事务
事务的ACID原则:
- 原子性
- 一致性
- 隔离性:多个业务可能操作同一个资源,防止数据损坏
- 持久性:事务一旦提交,结果不会再被影响
spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务管理
为什么需要事务? - 如果不配置事务,可能存在数据提交不一致的情况
- 如果不在spring中去配置声明式事务,就需要在代码中手动配置事务!
- 事务在项目的开发中十分重要,涉及到数据的一致性呵完整性问题。