目录
创建 bean 实例
Spring 针对 Bean 管理中创建对象提供注解
1)@Component :将类标识为普通组件
2)@Service :将类标识为业务层组件
3)@Controller r:将类标识为控制层组件
4)@Repository :将类标识为持久层组件
开启组件扫描
<context:component-scan base-package="com.gr.spring">
<!--
context:exclude-filter:排除扫描
type:设置排除扫描的方式 annotation:根据注解排除扫描
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
-->
</context:component-scan>
创建类,在类上面添加创建对象注解
@Service(value = "userService")
public class UserService {
public void add() {
System.out.println("service add.......");
}
}
属性注入
@Autowired:根据属性类型进行自动装配
@Qualifier:根据名称进行注入,必须与@Autowired同时使用
@Resource:可以根据类型注入,可以根据名称注入
@Value:注入普通类型属性
AOP 操作
配置
在 spring 配置文件中,开启注解扫描,开启生成代理对象
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
<!-- 开启 Aspect 生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
创建类,在类里面定义方法 (被代理类)
public class User {
public void add() {
System.out.println("add.......");
}
}
@Aspect 标定增强类
注释在创建的增强类上,创建方法,让不同方法代表不同通知类型 (代理类)
增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {
public void before() {//前置通知
System.out.println("before......");
}
}
@Before 前置通知
//@Before 注解表示作为前置通知
@Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void before() {
System.out.println("before.........");
}
@Pointcut 相同的切入点抽取
/*
相同切入点抽取
第一个*号代替“权限修饰符”和“返回值”部分表示“权限修饰符”和“返回值”不限
第二个*号,类名部分整体用*号代替,表示类名任意
第三个*号,在方法名部分,可以使用*号表示方法名任意
在方法参数列表部分,使用(..)表示参数列表任意
*/
@Pointcut("execution(* com.atguigu.spring5.aopanno.*.*(..))")
public void pointcut(){}
//JoinPoint参数 获取被增强类属性
@Before("pointCut()")
public void before(JoinPoint joinPoint){
//获取链接点所对应方法的签名信息
Signature signature = joinPoint.getSignature();
//获取链接点所对应方法的参数
Object[] args = joinPoint.getArgs();
System.out.println("LoggerAspect,方法:"+signature.getName()+",参数"+ Arrays.toString(args));
}
@AfterReturning 后置通知(返回通知)
/**
* 在返回通知中若要获取目标对象方法的返回值
* 只需要通过@AfterReturning注解的returning属性
* 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
*/
@AfterReturning(value = "pointCut()", returning = "result")
public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
//获取连接点所对应方法的签名信息
Signature signature = joinPoint.getSignature();
System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
}
@After 最终通知
@After("pointCut()")
public void after() {
System.out.println("after.........");
}
@AfterThrowing 异常通知
/**
* 在异常通知中若要获取目标对象方法的异常
* 只需要通过AfterThrowing注解的throwing属性
* 就可以将通知方法的某个参数指定为接收目标对象方法出现的异常的参数
*/
@AfterThrowing(value = "pointCut()", throwing = "ex")
public void afterThrowingAdviceMethod(JoinPoint joinPoint, Throwable ex){
//获取连接点所对应方法的签名信息
Signature signature = joinPoint.getSignature();
System.out.println("LoggerAspect,方法:"+signature.getName()+",异常:"+ex);
}
@Around 环绕通知
@Around("pointCut()")
//环绕通知的方法的返回值一定要和目标对象方法的返回值一致
public Object aroundAdviceMethod(ProceedingJoinPoint joinPoint){
Object result = null;
try {
System.out.println("环绕通知-->前置通知");
result = joinPoint.proceed();
System.out.println("环绕通知-->返回通知");
}
catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕通知-->异常通知");
} finally {
System.out.println("环绕通知-->后置通知");
}
return result;
}
@Order 设置增强类优先级
在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy{}
AOP测试实现实例
@Test
public void test(){
//获取IOC容器
ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
//创建AOP实现类.类型选择接口的类型(如Calculator)而非Object
Calculator calculator = ioc.getBean(Calculator.class);
calculator.div(1,1);
}
JdbcTemplate
什么是 JdbcTemplate
Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作
加入依赖:
<packaging>jar</packaging>
<dependencies>
<!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.1</version>
</dependency>
<!-- Spring 持久化层支持jar包 -->
<!-- Spring 在执行持久化层操作、与持久化层技术进行整合过程中,需要使用orm、jdbc、tx三个
jar包 -->
<!-- 导入 orm 包就可以通过 Maven 的依赖传递性把其他两个也导入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.1</version>
</dependency>
<!-- Spring 测试相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.1</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
</dependencies>
在 spring 配置文件配置数据库连接池:
<!--引入jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--注入 dataSource-->
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
测试类写法:
//指定当前测试类在spring的测试环境中执行,此时就可以通过注入的方式直接获取IOC容器中的bean
@RunWith(SpringJUnit4ClassRunner.class)
//设置spring测试环境的配置文件
@ContextConfiguration("classpath:spring-jdbc.xml")
public class JdbcTest {
@Autowired
private JdbcTemplate jdbcTemplate;
//增删改方式:
@Test
public void test(){
String sql = "insert into t_user values(0,?,?,?,?,?)";
jdbcTemplate.update(sql,"admin","123",22,"女","123@126.com");
}
//条件查询:
@Test
public void testUserById(){
String sql = "select * from t_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 3);
System.out.println(user);
}
//查询所有:
@Test
public void testAllUser(){
String sql = "select * from t_user";
List<User> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
query.forEach(System.out::println);
}
//查询单行单列数据
@Test
public void testCount(){
String sql = "select count(*) from t_user";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println(count);
}
}
@Transactional 开启事务的注解
所需依赖:
<packaging>jar</packaging>
<dependencies>
<!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.1</version>
</dependency>
<!-- Spring 持久化层支持jar包 -->
<!-- Spring 在执行持久化层操作、与持久化层技术进行整合过程中,需要使用orm、jdbc、tx三个
jar包 -->
<!-- 导入 orm 包就可以通过 Maven 的依赖传递性把其他两个也导入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.1</version>
</dependency>
<!-- Spring 测试相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.1</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
</dependencies>
在 spring 配置文件开启事务注解
<!--扫描组件-->
<context:component-scan base-package="com.gr.spring"></context:component-scan>
<!--引入jdbc.properties-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置JdbcTemplate-->
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
事务测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx_annotation.xml")
public class TxByAnnotation {
@Autowired
private BookController bookController;
@Test
public void testByBook(){
bookController.buyBook(1,2);
}
}
在 service 类上面(或者 service 类里面方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加方法上面
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
声明式事务管理参数配置
propagation:事务传播行为
REQUIRED:如果事务在运行,当前的方法就在这个事务内运行.否则就启动一个新的事务,并在 内运行
REQUIRED-NEW:当前的方法必须启动新事务,并在内运行.如果有事务正在运行,应该将它挂起
ioslation:事务隔离级别
timeout:超时时间
readOnly:是否只读(true ; false)
rollbackFor:回滚
noRollbackFor:不回滚
事务的传播行为:
标记在开启事务的方法上,事务回滚的默认属性,出现异常时由开启事务的方法进行回滚
@Transactional(propagation = Propagation.REQUIRED)
标记在被调用的事务方法上,出现异常时由被调用的事务方法进行回滚
@Transactional(propagation = Propagation.REQUIRES_NEW)