小白学习Spring(二)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用aop:目的是给已经存在的一些类和方法,增加额外的功能。前提是不改变原来类的代码

使用aspectj实现aop的基本步骤:

1.新建maven项目
2.加入依赖

​ 1)spring依赖
​ 2)aspectj依赖
​ 3)junit单元测试

加入依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.5</version>
</dependency>	
3.创建目标类

接口和他的实现类。
要做的是给类中的方法增加功能

4.创建切面类

普通类
1)在类的上面加入@Aspect
2)在类中定义方法,方法就是切面要执行的功能代码
在方法的上面加入aspectj中的通知注解,
例如@Before
有需要指定切入点表达式exection()

5.创建spring的配置文件

声明对象,把对象交给容器统一管理。
声明对象你可以使用注解或者xml配置文件bean
1)声明目标对象
2)声明切面类对象
3)声明aspectj矿建中的自动代理生成器标签
自动代理生成器:用来完成代理对象的自动创建功能的。

6.创建测试类

从spring容器中获取目标对象(实际就是代理对象)。
通过代理执行方法,实现aop的功能增强。

[掌握]@Before前置通知-方法有JoinPoint参数

在目标方法执行之前执行。被注解为前置通知的方法。可以包含一个JoinPoint类型参数。该类型的对象本身就是切入点表达式。通过该参数。可获取切入点表达式、方法签名、目标对象等。
​ 不光前置通知的方法。可以包含一个JoinPoint类型参数,所有的通知方法均可包含该参数。
​ 在方法之后自动执行的通知称为后置通知,可以应用于关闭流、上传文件、删除临时文件等功能。
​ 连接点指可以被切面织入的具体方法,通常业务接口中的方法均为连接点

<!-- 把对象交给spring容器 ,有spring容器统一创建,管理对象 -->
<!-- 声明目标对象 -->
<bean id="someService" class="com.sdyu.ch06.SomeServiceImpl"/>

<!-- 声明切面类对象 -->
<bean id="myAspect" class="com.sdyu.ch06.MyAspect"/>

<!-- 声明自动代理生成器  使用aspectj框架内部的功能,创建目标对象的代理对象。
	创建代理对象是在内存中实现的,修改目标对象的内存中的结构,创建为代理对象,
	所以目标对象就是被修改后的代理对象
	
	aspectj-autoproxy:会把spring容器中的所有目标都对象,一次性都生成代理对象。
-->
<aop:aspectj-autoproxy />
/**
 * @Aspect:是aspect框架中的注解。
 * 
 *  作用:表示当前类是切面类
 *	切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
 *	位置:在类定义的上面
 */
@Aspect
public class MyAspect {
	/**
	 * 定义方法,方法是实现切面功能的
	 * 方法定义的要求:
	 * 1.公共方法public
	 * 2.方法没有返回值
	 * 3.方法名称自定义
	 * 4.方法可以有参数,也可以没有参数
	 * 	如果有参数,参数不是自定义的,有几个参数类型可以使用。
	 * 
	 * 
	 */
/**

 * @Before:前置通知注解
 * 属性:value,是切入点表达式,表示切面的功能执行的位置。
 * 位置:在方法的上面
 * 
 * 特点:
 * 1.在目标方法之前先执行的
 * 2.不会改变目标方法的执行结果
 * 3.不会影响目标方法的执行
    */
   @Before(value = "execution(public void com.sdyu.ch06.SomeServiceImpl.doSome(String,Integer))")
   public void myBefore() {
   //就是你切面要执行的功能代码
   System.out.println("前置通知,切面功能:在目标方法之前输出执行时间:"+ new Date());
   }

}

```java
package com.sdyu.ch06;

public interface SomeService {

	void doSome(String name, Integer age);

}
package com.sdyu.ch06;

public class SomeServiceImpl implements SomeService {
	

	@Override
	public void doSome( String name,Integer age) {
		//给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
		System.out.println("=====目标方法doSome()=====");
		
	}

}

JoinPoint参数使用

  • 指定通知方法中的参数:JoinPoint
  • JoinPoint :业务方法,要加入切面功能的业务方法
  • 作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参。
  • 如果你的切面功能中需要用到方法的信息,就加入JoinPoint
  • 这个JoinPoint 参数的值是由框架赋予,必须是第一个位置的参数
  • ​ public void MyAfterReturning(JoinPoint jp,Object res) {//JoinPoint要在第一个参数

@Before(value = "execution(* com.sdyu.ch06.SomeServiceImpl.doSome(..))")
	public void myBefore(JoinPoint jp) {
		//就是你切面要执行的功能代码
		System.out.println("前置通知,切面功能:在目标方法之前输出执行时间:"+ new Date());//获取方法的完整定义System.out.println("方法的签名(定义):"+jp.getSignature());System.out.println("方法的名称"+jp.getSignature().getName());
​	
​	Object args [] =jp.getArgs();
​	
​	for(Object i :args) {System.out.println("参数="+i);}
}



### [掌握]@AfterReturn后置通知-注解有returning属性

@Aspect
public class MyAspect {
/**
* 后置通知定义方法,方法是实现切面功能的
* 方法定义的要求:
* 1.公共方法public
* 2.方法没有返回值
* 3.方法名称自定义
* 4.方法可以有参数,也可以没有参数
* 如果有参数,参数不是自定义的,有几个参数类型可以使用。
/
/
*
* @AfterReturning:后置通知
* 属性:1.value切入点表达式
* 2.returning 自定义的变量,表示目标方法的返回值的。
* 自定义变量名必须和通知方法的形参名一样。
* 位置:在方法定义的上面
* 1。在目标方法之后执行的。
* 2.能够获取到目标方法的返回值,可以根据这个返回值做不同的处理功能
* 3.可以修改这个返回值
*
* 后置通知的执行
* Object res = doOther();
* myAfterReturning(res);
* 参数传递:传值,传引用
* System.out.println(“res”+res)
// */

//	@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "res")
//	public void MyAfterReturning(Object res) {
//			//Object res:是目标方法执行后的返回值,根据返回值做你的切面的功能处理
//		System.out.println("后置通知,在目标方法之后执行的,获取的返回值是:"+res);
//		if(res.equals("abcd")) {
//			//做一些功能
//		}else {
	
//			//做一些功能
//		}
//		
//		//修改目标方法的返回子 ,看一下是否会影响 最后的发给发调用结果
//		if(res != null) {
//			res = "hello";
//		}
//	}
	@Override
	public Student doOther2(String name, Integer age) {
		Student student = new Student();
		student.setName("大");
		student.setAge(23);
		return null;
	}

[掌握]@Around环绕通知-增强方法有ProceedingJoinPoint参数

/**

 * 环绕通知方法的定义格式
 * 1.public
 * 2.必须要有一个返回值
 * 3.方法名称自定义
 * 4.方法有参数,固定的参数 ProceedingJoinPoint
   */

/**

 * @throws Throwable 

 * @Around:环绕通知

 * 属性:value切入点表达式

 * 位置:在方法的定义什么

 * 特点:

 * 1.他是功能最强的通知

 * 2.在目标方法的前和后都能增强功能。

 * 3.控制目标方法是否被调用执行

 * 4.修改原来的目标方法的执行结果。影响最后的调用结果

 * 

 * 

 * 环绕通知,等于jdk动态代理,InovactionHandler接口

 * 

 * 参数:ProceedingJoinPoint 就等同于Method

 * 作用:执行目标方法的

 * 返回值:就是目标方法的执行结果,可以被修改。

 * 

 * 环绕通知:经常做实物,在目标方法之前开启事务,执行目标方法,在目标方法

 * 之后提交事务
   */


```java
   @Around(value = "execution(* *..SomeService.doFirst(..))")
   public Object myAround(ProceedingJoinPoint pjp) throws Throwable {

   String name ="";
   //获取第一个参数值
   Object args[] =pjp.getArgs();
   if(args != null && args.length > 1) {
   	Object arg = args[0];
   	name=(String)arg;
   }
   //实现环绕通知
   Object result =null;
   System.out.println("环绕通知:在目标方法之前,输出事件:"+new Date());


​		
​		

​	if("zhangsan".equals(name)) {
​		//符合条件,调用目标方法
​		//1.目标方法调用
​		result = pjp.proceed();//method.invoke();
​	}
​	
​	System.out.println("环绕通知:在目标方法之后,输出事件:"+result+new Date());
​	
​	//2.在目标方法的前或者后,加入功能
​	
​	//修改目标的执行结果,影响方法执行时,增强了功能
​	if(result != null) {
​		result = "Hello Aspect AOP";
​	}
​	
​	//返回目标方法的执行结果
​	return result;
}

[了解]@AfterThrowing异常通知-注解中有throwing属性

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;




@Aspect
public class MyAspect {
	/**
	 * 异常通知方法的定义格式
	 * 方法定义的要求:
	 * 1.公共方法public
	 * 2.方法没有返回值
	 * 3.方法名称自定义
	 * 4.方法有个Exception,如果有是JoinPoint
	 */
	/**
	 *  @AfterThrowing:异常通知
	 *  	属性:1.value 切入点表达式
	 *  		 2.throwing 自定义的变量,表示目标方法抛出的异常对象。
	 *  			变量名必须和方法的参数名一样
	 *  特点:
	 *  	1.在目标方法抛出异常时执行的
	 *  	2.可以做异常的监控程序,监控目标方法执行时是不是有异常。
	 *  		如果有异常,可以发送邮件,短信进行通知
	 *  		
	 *		执行就是:
	 *		try{
	 *		SomeServiceImpl.doSecond(..)
	 *	}catch(Exception e){
	 *		myAfterThrowing(e);
	 *	}
	 */
	@AfterThrowing(value="execution(* *..SomeServiceImpl.doSecond(..))",throwing ="e")
	public void myAfterThrowing(Exception e) {
		System.out.println("异常通知:方法发生异常,执行:"+e.getMessage());
		//发送邮件,短信,通知开发人员
	}
​		
}
public class MyTest2 {

	@Test
	public void test01() {
		String config="applicationContext.xml";
		ApplicationContext acx = new ClassPathXmlApplicationContext(config);
		

		SomeService sd = (SomeService) acx.getBean("someService");
		sd.doSecond();
	}

}

[了解]@After最终通知

@Aspect
public class MyAspect {
	/**
	 * 异常通知方法的定义格式
	 * 方法定义的要求:
	 * 1.公共方法public
	 * 2.方法没有返回值
	 * 3.方法名称自定义
	 * 4.无参数,如果有还是JoinPoint,
	 */
	/**
	 * @After:最终通知
	 * 	属性:value 切入点表达式
	 * 
	 * 	位置:在方法的上面
	 * 
	 * 特点:
	 * 1.总是会执行
	 * 2.在目标方法之后执行的
	 * 
	 */
	@After(value="execution(* *..SomeServiceImpl.doThird(..))")
	public void myAfter() {
		System.out.println("执行最终通知,");//有异常也会被执行
	}
}
public class MyTest2 {
	@Test
	public void test01() {
		String config="applicationContext.xml";
		ApplicationContext acx = new ClassPathXmlApplicationContext(config);
		SomeService sd = (SomeService) acx.getBean("someService");
		sd.doThird();
	}

}

@Pointcut定义切入点(辅助)

@Aspect
public class MyAspect {
	/**
	 * 异常通知方法的定义格式
	 * 方法定义的要求:
	 * 1.公共方法public
	 * 2.方法没有返回值
	 * 3.方法名称自定义
	 * 4.无参数,如果有还是JoinPoint,
	 */
	/**
	 * @After:最终通知
	 * 	属性:value 切入点表达式
	 * 
	 * 	位置:在方法的上面
	 * 
	 * 特点:
	 * 1.总是会执行
	 * 2.在目标方法之后执行的
	 * 
	 */
	

	@After(value="mypt()")
	public void myAfter() {
		System.out.println("执行最终通知,方法之后执行");
	}
	
	@Before(value="mypt()")
	public void myBefore() {
		System.out.println("执行前置通知,方法之前执行");
	}
	
	/**
	 * @Pointcut:定义和管理切入点表达式,如果你的项目中有多少个切入点表达式是重复的,可以复用的。
	 * 			可以使用@Pointcut
	 * 	属性:value 切入点表达式
	 * 	位置:在自定义的方法上面
	 * 	特点:
	 * 	当使用@Pointcut定义在一个方法的上面,此时这个方法的名称就是切入点表达式的别名,、
	 *  其他的通知中,value属性就可以使用这个方法名称,代替切入点表达式了
	 */
	@Pointcut(value="execution(* *..SomeServiceImpl.doThird(..))" )
	private void mypt() {
		//无需代码,
	}

}
public class MyTest2 {
	@Test
	public void test01() {
		String config="applicationContext.xml";
		ApplicationContext acx = new ClassPathXmlApplicationContext(config);
		

		SomeService sd = (SomeService) acx.getBean("someService");
		sd.doThird();
	}

}

如果有接口使用cglib

	<!-- 
	如果你期望目标类有接口,使用cglib代理
	proxy-target-class="true" :告诉框架,要用cglib代理
 -->
 
<aop:aspectj-autoproxy proxy-target-class="true"/>

Spring整合Mybatis集成

用的技术是:IOC

为什么IOC:能把mybatis和spring集成在一起,像一个框架,因为IOC可以创建框架

可以把Mybatis框架中的对象交给spring统一,开发人员从spring中获取对象。

开发人员不用同时面对两个或多个框架了,就面对一个spring

mybatis使用步骤,对象

1.定义dao接口,StudentDao

2.定义mapper文件StudentDao.xml

3.定义mybatis的主配置文件mybatis.xml

4.创建dao的代理对象,SqlSession.getMapper(StudentDao.class);

List students = dao.selectStudents();

要使用dao对象,需要使用getMapper()方法,

怎么能使用getMapper()方法,需要哪些条件

1.获取SqlSession对象 ,需要使用SqlSessionFactory的openSession()方法

2.创建SqlSessionFactory对象。使用Factory能获取SqlSession,有了SqlSession能有dao,目的就是获取dao对象

Factory创建需要读取主配置文件

我们会使用独立的连接池替换mybatis默认自己带的,把连接池类也交给spring来创建。

主配置文件

1.数据库信息

 <environments default="online">
  <!--唯一值 id  -->
    <environment id="mydev">
    <!-- 数据源 -->
      <transactionManager type="JDBC"/>
      <!-- 连接池 -->
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/student?serverTimezone=UTC&amp&characterEncoding=utf-8
jdbc.user=root
jdbc.password=123456

2.mapper文件位置

 <mappers>
    <mapper resource="com/sdyu/dao/StudentDao.xml"/>
  </mappers>

=========================================================================================================

通过以上说明,我们需要让spring创建以下对象

1.独立的连接池类的对象,使用阿里的druid连接池

2.SqlSessionFactory对象

3.创建dao对象

需要学习就是上面三个对象的创建语法,使用xml的bean标签。(目前)

总体依赖:

 <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- spring核心 -->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.5</version>
	</dependency>
	<!-- spring做事务的 -->
	 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.5</version>
	</dependency>
	  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.5</version>
	</dependency>
	<dependency>
	<groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.5.6</version>
   </dependency>
	<!-- mybatis和spring集成依赖 -->
	<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
	</dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.22</version>
    </dependency>

    <!-- 阿里数据库连接池 -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.5</version>
    </dependency>

插件:

 <build>
  <resources>
   <resource>
  	<directory>src/main/java</directory><!-- 所在的目录 -->

  	<includes>
  	<!-- 包括目录下的.properties.xml 文件都会扫描 -->
  	 <include>**/*.properties</include>
  	 <include>**/*.xml</include>
  	</includes>
  	
  	<filtering>false</filtering>
  	</resource>

  </resources>
    <plugins>
    

      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
         <sorce>1.8</sorce>
         <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>

以后常用mybatis模板

<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>

  <settings>
      <setting name="logImpl" value="STDOUT_LOGGING"/>
  </settings>

  <!-- 设置别名 -->
  <typeAliases>
  	<!-- name:实体类所在的包名 -->
  	<package name="com.sdyu.entity"/>
  </typeAliases>

  <mappers>
  <!-- name:是包名,这个包中所有的mapper.xml 一次性加载

   -->
    <package name="com.sdyu.dao"/>
  </mappers>

</configuration>

application.xml

<?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:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://mybatis.org/schema/mybatis-spring 
	http://mybatis.org/schema/mybatis-spring-1.2.xsd">

	<!-- 声明数据源DataSource,作用是连接数据库 -->
	 <bean id="mydataSource" class="com.alibaba.druid.pool.DruidDataSource" 
	 init-method="init" 
	 destroy-method="close"> 
	 <!-- 使用set注入给DruidDataSrouce提供连接数据库信息 -->
	 <property name="url" value="jdbc:mysql://localhost:3306/student?serverTimezone=UTC&amp; characterEncoding=utf-8" />
	 <property name="username" value="root" />
	 <property name="password" value="123456" />
	 <property name="maxActive" value="20" />
	 </bean>
	
	<!-- 声明的是mubatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory -->
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<!-- set注入,把数据连接池赋给了dataSource -->
		<property name="dataSource" ref="mydataSource"/>
	<!-- mybatis主配置文件 
	
		configLocationResource属性是Resource类型,读取配置文件
		他的赋值,使用value,指定文件的路径,使用classpath:表示文件的位置
	-->
		<property name="configLocation" value="classpath:Mybatis.xml"/>
	</bean>

</beans>

jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/student?serverTimezone=UTC&amp&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.maxActive=20

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值