Spring总结
IOC
创建对象 (XML)
p名称空间:属性注入
xmlns:p=“http://www.springframework.org/schema/p”
创建对象是在spring配置文件中的<bean></bean>
标签中完成
<bean id="book" class="com.study.spring5.entity.Book">
<property name="bname" value="红楼梦"></property>
</bean>
<bean>
标签中可以使用很多属性
属性 | 解释 |
---|---|
id | 作为该对象的唯一标识 |
class | 类的全路径 |
p:属性名 | p名称空间注入属性 |
scope | 设置bean为单实例还是多实例 singleton:单实例 prototype:多实例 |
autowire | 自动装配 byName:根据属性名称注入 byType:根据属性类型注入 |
autowire=“byName”:把与 bean 的属性具有相同名字的其他 bean 自动装配到 bean 的对应属性中。比如<bean>(A)
中有一个属性名 与 bean(B) id 相等的属性,并且bean(B)是外部bean,那么配上autowire="byName"后,Spring会自动将bean(B) 注入到<bean(A)>
property
标签中可以使用很多属性/标签
property:是用来给bean的属性配置要注入的值的。这些值可以是bean或者简单值
属性 | 解释 |
---|---|
name | 类中属性名 |
value | 设定基本数据类型的值(包含String) |
<null/> | 注入空值 |
<![CDATA[<<"注入的特殊字符">>]]> | 注入特殊字符 |
ref=“bean id” | 外部bean,注入引用类型 |
<bean> | 内部bean 外部bean能加的标签,内部bean也能加,只是位置不同 |
name=“bean id.属性名” value/ref = “” | 级联赋值 前提是,在 <bean> 已经引入了该bean |
property
下引入集合
属性 | 解释 |
---|---|
<array><value>值 | 数组 |
<list><value>值 | list |
<set><value>值 | set |
<map><entry key="" value=""> | map |
------------------------------------- | ------------------------------------- |
<ref bean="bean id"></ref> | 集合中引入对象 替换上面 <value> 位置 |
constructor-arg
标签中可以使用很多属性
constructor-arg:通过构造函数注入属性
属性 | 解释 |
---|---|
name | 类中属性名 |
value | 设定基本数据类型的值(包含String) |
引入外部属性文件
引入context
名称空间
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
使用el表达式,将外部属性值取出
<!--引入外部文件-->
<!--classpath: 指的是src目录下-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}" />
<property name="url" value="${prop.url}" />
<property name="username" value="${prop.username}" />
<property name="password" value="${prop.password}" />
</bean>
创建对象 (注解)
@Component
:普通组件@Service
:一般用于业务逻辑层或service层上@Controller
:一般用于web层@Repository
:一般用于dao层
1、注入context
名称空间
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
2、开启组件扫描
base-package: 要扫描那个包
如果扫描多个包:①多个包使用逗号隔开、 ②扫描包上层目录(多个注解类在同一个包下)
<context:component-scan base-package="com.study.spring5"></context:component-scan>
3、在类上加上注解
注解后面的 value 是设置 id
在注解里面value属性值可以省略不写,
默认值是类名称,首字母小写
@Component(value = "userService")
public class UserService {
基于注解方式实现属性注入
@Autowired
:根据属性类型进行自动装配@Qualifier
:根据名称进行注入@Resource
:可以根据类型注入,可以根据名称注入@Value
:注入普通类型属性
提醒一点:
@Qualifier
注解和上面@Autowired一起使用
@Autowired
是根据 属性类型来注入,但如果有多个相同类型的bean,使用这个注解就麻烦了,比如接口的实现类
因此,使用 @Qualifier
通过名称(@Autowired
设置的 value) 就可以很好的解决这个问题
public class UserService {
@Autowired //根据类型注入
@Qualifier(value = "userDaoImpl1") //指定value
private UserDao userDao;
@Resource:使用方法和@Autowired
/@Qualifier
一样
完全注解开发
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = "com.study.spring5")
public class SpringConfig {
}
AOP
AOP术语
1、连接点:类里面哪些方法可以被增强,这些方法称为连接点
2、切入点:实际被真正增强的方法,称为切入点
3、通知(增强):(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多钟类型
前置通知(@Before
):增强方法之前,执行
后置通知(@AfterReturning
):增强方法之后,执行
环绕通知(@Around
):增强方法前后,执行
异常通知(@AfterThrowing
):增强方法出现异常,执行
最终通知(@After
):不管增强方法是否出现异常,都执行
4、切面:是动作。把通知应用到切入点过程
切入点表达式
切入点表达式作用:知道对哪个类里面的哪个方法进行增强
语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]))
如:对 com.atguigu.dao.BookDao 类里面的 add 进行增强
execution(* com.atguigu.dao.BookDao.add(..))
注解实现AOP操作
1、在 spring 配置文件中,引入 context 名称空间 和 aop 名称空间
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
2、开启注解扫描
<context:component-scan base-package="com.study.spring5.aopanno"></context:component-scan>
3、开启Aspect生成代理对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4、在增强类上面添加注解 @Aspect
@Component
@Aspect //生成代理对象
public class UserProxy {
}
5、添加通知注解,并编写切入点表达式
@Component
@Aspect //生成代理对象
//@Order(1) //设置优先级,数字越小,优先级越高
public class UserProxy {
@Before(value = "execution(* com.study.spring5.aopanno.User.add(..))")
public void before() {
System.out.println("我是前置通知...");
}
}
不同类型注解
@Before(value = "切入点表达式")
:前置通知@After(value = "切入点表达式")
:后置通知(最终通知)
在被增强方法之后执行完后执行@AfterReturning(value = "切入点表达式")
:后置通知(返回通知)
在被增强方法返回结果之后执行@Around(value = "切入点表达式")
:环绕通知@AfterThrowing(value = "切入点表达式")
:异常通知
完全注解开发
@Configuration
@ComponentScan(basePackages = {"com.study"})
@EnableAspectJAutoProxy(proxyTargetClass = true) //开启动态代理,默认是false
public class ConfigAop {
}
事务
配置Spring事务
①在 spring 配置文件引入名称空间 tx
和context
xmlns:context=“http://www.springframework.org/schema/context”
xmlns:tx=“http://www.springframework.org/schema/tx”
http://www.springframework.org/schema/context http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
②开启注解
<!--开启注解扫描-->
<context:component-scan base-package="com.study.spring5"></context:component-scan>
③配置数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///user_db"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
④配置JdbcTemplate bean
<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入 dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
⑤配置事务管理器
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
Spring声明式事务管理(注解方式)
@Transactional
,这个注解添加到类上面,也可以添加方法上面- 如果把这个注解添加类上面,这个类里面所有的方法都添加事务
- 如果把这个注解添加方法上面,为这个方法添加事务
@Service
@Transactional
public class UserService {
Spring声明式事务管理(事务参数)
事务参数 | 解释 |
---|---|
propagation() | 事务传播行为 |
isolation() | 事务隔离级别 |
timeout() | 超时时间 |
readOnly() | 是否只读 |
rollbackFor() | 回滚 |
noRollbackFor() | 不回滚 |
回滚操作
@Service
@Transactional(noRollbackFor = {ArithmeticException.class})
public class UserService {
事务传播行为
PROPAGATION_REQUIRED(默认)
:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中
PROPAGATION_REQUIRES_NEW
:新建事务,如果当前存在事务,把当前事务挂起
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserService {
隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED(读未提交) | 有 | 有 | 有 |
READ COMMITTED(读已提交) | 无 | 有 | 有 |
REPEATABLE READ(可重复读) | 无 | 无 | 有 |
SERIALIZABLE(串行化) | 无 | 无 | 无 |
@Service
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class UserService {
完全注解开发
@Configuration //配置类
@ComponentScan(basePackages = "com.study") //注解扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
//创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql:///user_db");
druidDataSource.setUsername("root");
druidDataSource.setPassword("123456");
return druidDataSource;
}
@Bean
//在IOC容器中,已经存在了DataSource对象
//DataSource dataSource:根据类型,找到相应的对象,注入到JdbcTemplate中
//到ioc容器中根据类型找到dataSource
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}