初识Spring


可能比较快,这只是我一个学习的笔记

什么是Spring?

javaSE/EE full-stack 轻量级开源框架 、以IoC 和 AOP为内核、使用基本的javaBean来完成EJB晚餐的工作

开发中的体系

实际开发钟使用三层体系架构 :表示层、业务逻辑层、持久层(DAO数据库层)
Spring框架特点:
1.非入侵式设计
2.方便解耦、简化开发
3.支持AOP
4.支持声明式事务处理
5.方便程序测试
6.方便集成各种优秀框架在这里插入图片描述

Spring的核心容器

Spring会控制程序之间的关系,并不是由Spring直接控制。
Spring核心容器BeanFactory和ApplicationContext
ApplicationContext比较常用 通常两种配置方法如下:
1.

// 定义配置文件路径
		String xmlPath = "com/itheima/annotation/beans6.xml";
		// 加载配置文件
		ApplicationContext applicationContext = 
				new ClassPathXmlApplicationContext(xmlPath);

在这里插入图片描述

依赖注入与控制反转

DI全称依赖注入与IoC(控制反转)的含义相同,两个角度描述同一个概念

DISping 容器负责将被依赖对象赋值调用者的成员变量,相当于注入实例,这就是依赖注入
IoC使用Spring框架后。对象不再有调用者来创建、是Spring容器创建、容器会负责控制程序之间的关系

Spring中的bean

Bean :零件 、java类对象
Bean的配置 :properties(文件)、XML(id、name),通常是使用XML的方式在这里插入图片描述
Bean的实例化:构造器的实例化、静态工厂实例化、实例工厂实例化,这里介绍常用的构造器实例化
java类bean1里面什么都没有

package com.itheima.instance.constructor;
import org.springframework.context.ApplicationContext;
import 
	org.springframework.context.support.ClassPathXmlApplicationContext;
public class InstanceTest1 {
	public static void main(String[] args) {
		// 定义配置文件路径
		 
		String xmlPath = "com/itheima/instance/constructor/beans1.xml";
		// ApplicationContext在加载配置文件时,对Bean进行实例化
		ApplicationContext applicationContext = 
							new ClassPathXmlApplicationContext(xmlPath);
		Bean1 bean = (Bean1) applicationContext.getBean("bean1");
		 System.out.println(bean);
		 
	
	}
}

bean1在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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 	http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
	
	<bean id="bean1" class="com.itheima.instance.constructor.Bean1" />
</beans>

控制台输出:bean1的地址

五月 18, 2020 11:56:13 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1a6c5a9e: startup date [Mon May 18 11:56:13 CST 2020]; root of context hierarchy
五月 18, 2020 11:56:13 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [com/itheima/instance/constructor/beans1.xml]
com.itheima.instance.constructor.Bean1@737996a0

bean的作用域
在这里插入图片描述
bean的装配方式:

 1.XML:
      	         a.设值注入 <property name="usename" value="张三"></property>
      	   		 b.构造注入<ocnstructor-arg index="0" value="tom"//index 参数位置,从0开始
      	   		 缺点:工作复杂

      	   	2.Annotation(注释)@component:描述Spring中的Bean
      	   	    @Repository:DAO(数据访问层) Spring中的Bean
      	   	    @Service: 业务层的类标识
      	   	    @Controller: 控制层的类标识(页面管理)
      	   	    @Autowired: Bean的属性变量 (属性、构造)注入
      	   	    @Resource: 与 @Autowired 功能一样
      	   	    @Qualifier :区分同名
  

            类扫描:<context : component-scan  base-package="包名"/> //自动扫描包内的Bean
		 <context:component-scan base-package="com.itheima.annotation" />
            3.自动装配:设置autowire属性值来实现自动装配 配置到其他的<bean>内实现自动:
		<bean id="userDao" 
		class="com.itheima.annotation.UserDaoImpl" />
	<bean id="userService" 
	  class="com.itheima.annotation.UserServiceImpl" autowire="byName" />
	  ///chapter02/src/com/itheima/assemble/XmlBeanAssembleTest.java

在这里插入图片描述

Spring中的AOP

AOP :面向切面编程,是面向对象编程(OOP)的补充在这里插入图片描述
动态代理:
JDK的动态代理:代理对象有一个或者多个接口
入口是Proxy,Proxy有个静态的方法 getProxyClass(class,interfaces)传入类加载器和一组接口,它会给你返回Class对象。创建出一个·实例关键就是得到得到对应的Class对象,new出对象直接返回的是对象。
能否不写代理类,而直接得到代理Class对象,然后根据它创建代理实例(反射)?Class对象包含了一个类的所有信息:构造器、方法—>不写代理类从和获取类信息—>代理类和目标类理应实现同一组接口《之所以同一组接口,为了尽可能的保证代理对象内部结构和目标对象一致,这样我们对代理对象的操作最终都可以转移到目标对象的身上,代理对象可以专注于增强代码的编写,后续多的需求不用使用底层源代码,代理对象处理后多的需求》
Proxy.getProxyClass()这个方法的本质就是:以Class造Class
代理Class的构造器船创建对象,需要传入InvocationHandler,每次调用代理对象的方法最终都会调用InvocationHandler的invoke();

这里引用了另外一位前辈的关于动态代理的理解,里面写的很好,所以在此感谢

动态代理的对象必须实现一个或者多个接口,为此CGLIB刚刚好解决了这个问题
CGLIB:无接口 、拦截器 CglibProxy implements MethodInterceptor// 实现接口

基于代理的AOP实现
本地代码com.itheima.factorybean类
** AspectJ开发**
1.基于XML的声明式AspectJ,所有切面、切入点和通知都必须定义在aop:config>元素内
2.基于注解AspectJ的开发
xml:
1.定义配置切面aop:aspect id:标识符 ref:全类
2.定义配置切点<aop: pointcut> id:标识符 expression :表达式<aop:pointcut id=“myPointCut”
expression=“execution(* com.itheima.jdk..(…))”
3.配置通知 aop:aspect的子元素配置通知
在这里插入图片描述
MyAspect

package com.itheima.aspectj.xml;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/**
 *切面类,在此类中编写通知
 */
public class MyAspect {
	// 前置通知
	public void myBefore(JoinPoint joinPoint) {
		System.out.print("前置通知 :模拟执行权限检查...,");
		System.out.print("目标类是:"+joinPoint.getTarget() );
		System.out.println(",被织入增强处理的目标方法为:"
                            +joinPoint.getSignature().getName());
	}
	// 后置通知
	public void myAfterReturning(JoinPoint joinPoint) {
		System.out.print("后置通知:模拟记录日志...," );
		System.out.println("被织入增强处理的目标方法为:"
                          + joinPoint.getSignature().getName());
	}
	/**
	 * 环绕通知
	 * ProceedingJoinPoint 是JoinPoint子接口,表示可以执行目标方法
	 * 1.必须是Object类型的返回值
	 * 2.必须接收一个参数,类型为ProceedingJoinPoint
	 * 3.必须throws Throwable
	 */
	public Object myAround(ProceedingJoinPoint proceedingJoinPoint) 
             throws Throwable {
		// 开始
		System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
		// 执行当前目标方法
		Object obj = proceedingJoinPoint.proceed();
		// 结束
		System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
		return obj;
	}
	// 异常通知
	public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
		System.out.println("异常通知:" + "出错了" + e.getMessage());
	}
	// 最终通知
	public void myAfter() {
		System.out.println("最终通知:模拟方法结束后的释放资源...");
	}
}

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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<!-- 1 目标类 -->
	<bean id="userDao" class="com.itheima.jdk.UserDaoImpl" />
	<!-- 2 切面 -->
	<bean id="myAspect" class="com.itheima.aspectj.xml.MyAspect" />
	<!-- 3 aop编程 -->
	<aop:config>
        <!-- 配置切面 -->
		<aop:aspect ref="myAspect">
		  <!-- 3.1 配置切入点,通知最后增强哪些方法 -->
		  <aop:pointcut  id="myPointCut" 
		                 expression="execution(* com.itheima.jdk.*.*(..))"
				                                      />
			<!-- 3.2 关联通知Advice和切入点pointCut -->
			<!-- 3.2.1 前置通知 -->
			<aop:before method="myBefore" pointcut-ref="myPointCut" />
			<!-- 3.2.2 后置通知,在方法返回之后执行,就可以获得返回值
			 returning属性:用于设置后置通知的第二个参数的名称,类型是Object -->
			<aop:after-returning method="myAfterReturning"
				                  pointcut-ref="myPointCut" returning="returnVal" />
			<!-- 3.2.3 环绕通知 -->
			<aop:around method="myAround" pointcut-ref="myPointCut" />
			<!-- 3.2.4 抛出通知:用于处理程序发生异常-->
			<!-- * 注意:如果程序没有异常,将不会执行增强 -->
			<!-- * throwing属性:用于设置通知第二个参数的名称,类型Throwable -->
			<aop:after-throwing method="myAfterThrowing"
				pointcut-ref="myPointCut" throwing="e" />
			<!-- 3.2.5 最终通知:无论程序发生任何事情,都将执行 -->
			<aop:after method="myAfter" pointcut-ref="myPointCut" />
		</aop:aspect>
	</aop:config>
</beans>

测试类

package com.itheima.aspectj.xml;
import org.springframework.context.ApplicationContext;
import 
    org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.jdk.UserDao;
// 测试类
public class TestXmlAspectj {
	public static void main(String args[]) {
		String xmlPath = 
                         "com/itheima/aspectj/xml/applicationContext.xml";
		ApplicationContext applicationContext = 
                          new ClassPathXmlApplicationContext(xmlPath);
		// 1 从spring容器获得内容
		UserDao userDao = (UserDao) applicationContext.getBean("userDao");
		// 2 执行方法
		userDao.addUser();
		userDao.deleteUser();
	}
}
///chapter03/src/com/itheima/aspectj/xml/TestXmlAspectj.java

控制台结果
在这里插入图片描述

Spring的事务管理

三个核心接口
在这里插入图片描述

			1.PlatformTransactionManager接口:代表事务管理接口,不知道底层
			    a.getTransation 获取事务状态
			    b.commit 提交事务
			    c.rollback 回滚事务
			2.TransactionDefinition接口:事务描述对象,定义事务规则
			    a.getName 获取事务对象名称
			    b.getlsolationLevel 获取事务的隔离级别
  				    c.getPropagationBehavior 获取事务的传播行为
			    d.getTimeout   获取队伍的超时时间
			    e.isReadOnly  是否事务只读
			3.TransactionStaus接口:事务状态
			    a.flush 刷新事务 (写入数据)
			    b.hasSavepion()  获取事务是否存在保存点
			    c.isCompleted()  获取事务是否完成
			    d.isNewTeansaction() 获取是否为新事物
			    e.isRollbackOnuly() 获取事务是否回滚
			    f.setRollbackOnly()  设置事务是否回滚 

管理的实现

1.XML的方式的声明事务(理解)
		             a.配置<tx:advice>中重点配置的<tx:method>
				 2.Annotation的方式(掌握,非常熟悉)<bean id="transactionManager" class=
     "org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>	
    <!-- 5.注册事务管理器驱动 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
	//注意这里的扫描不是chapter05的,是chapter10的
	//这里没有是因为已经配置了实体的Bean
	<!-- 开启扫描 --> 
	<context:component-scan base-package="com.itheima.service" />
	//chapter05

在对应的需要事务的方法前加上 @Transactional

Spring数据库开发

在这里插入图片描述
直接上实例:

  1. 配置一个

applicationContext.xml环境

<beans xmlns="http://www.springframework.org/schema/beans"
	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-4.3.xsd">
	<!-- 1配置数据源 -->
	<bean id="dataSource" class=
     "org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--数据库驱动 -->
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> 
		<!--连接数据库的url -->
		<property name="url" value="jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false&amp;serverTimezone=UTC" />
		<!--连接数据库的用户名 -->
		<property name="username" value="root" />
		<!--连接数据库的密码 -->
		<property name="password" value="123456" />
	</bean>
	<!-- 2配置JDBC模板 -->
	<bean id="jdbcTemplate" 
		   class="org.springframework.jdbc.core.JdbcTemplate">
		<!-- 默认必须使用数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!--定义id为accountDao的Bean-->
	<bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
		<!-- 将jdbcTemplate注入到accountDao实例中 -->
		<property name="jdbcTemplate" ref="jdbcTemplate" />
	</bean>
	
</beans>
  1. AccountDao接口的方法实现
package com.itheima.jdbc;
import java.util.List;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class AccountDaoImpl implements AccountDao {
	// 声明JdbcTemplate属性及其setter方法
	private JdbcTemplate jdbcTemplate;
	
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
    // 添加账户
	public int addAccount(Account account) {
		// 定义SQL
		String sql = "insert into account(username,balance) value(?,?)";
		// 定义数组来存放SQL语句中的参数
		Object[] obj = new Object[] { 
                           account.getUsername(), 
                           account.getBalance() 
         };
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, obj);
		return num;
	}
	// 更新账户
	public int updateAccount(Account account) {
		// 定义SQL
		String sql = "update account set username=?,balance=? where id = ?";
		// 定义数组来存放SQL语句中的参数
		Object[] params = new Object[] { 
                               account.getUsername(), 
                               account.getBalance(), 
                               account.getId() 
          };
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, params);
		return num;
	}
	// 删除账户
	public int deleteAccount(int id) {
		// 定义SQL
		String sql = "delete  from account where id = ? ";
		// 执行添加操作,返回的是受SQL语句影响的记录条数
		int num = this.jdbcTemplate.update(sql, id);
		return num;
	}
	
	// 通过id查询账户数据信息
	public Account findAccountById(int id) {
	    //定义SQL语句
	    String sql = "select * from account where id = ?";
	    // 创建一个新的BeanPropertyRowMapper对象
	    RowMapper<Account> rowMapper = 
	new BeanPropertyRowMapper<Account>(Account.class);
	    // 将id绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录
	    return this.jdbcTemplate.queryForObject(sql, rowMapper, id);
	}
	// 查询所有账户信息
	public List<Account> findAllAccount() {
	    // 定义SQL语句
	    String sql = "select * from account";
	    // 创建一个新的BeanPropertyRowMapper对象
	    RowMapper<Account> rowMapper = 
	new BeanPropertyRowMapper<Account>(Account.class);
	    // 执行静态的SQL查询,并通过RowMapper返回结果
	    return this.jdbcTemplate.query(sql, rowMapper);
	}

}

  1. Account账户类和接口
public class Account {
	private Integer id;       // 账户id
	private String username; // 用户名
	private Double balance;  // 账户余额
	public Integer getId() {
		return id;
	}//下面使它的set和get方法这里就不重复了
	//下面是Account接口类的空方法
	public interface AccountDao {
	// 添加
	public int addAccount(Account account);
	// 更新
	public int updateAccount(Account account);
	// 删除
	public int deleteAccount(int id);
	
	// 通过id查询
	public Account findAccountById(int id);
	// 查询所有账户
	public List<Account> findAllAccount();
}
  1. 测试类:
public class JdbcTemplateTest {
	/**
	 * 使用execute()方法建表
//	 */

	@Test
	public void mainTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取JdbcTemplate实例
	    JdbcTemplate jdTemplate = 
	            (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
	    // 使用execute()方法执行SQL语句,创建用户账户管理表account
	    jdTemplate.execute("create table account(" + 
	                           "id int primary key auto_increment," +
	                           "username varchar(50)," + 
	                           "balance double)");
	    System.out.println("账户表account创建成功!");
	}

	@Test
	public void addAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    AccountDao accountDao = 
	            (AccountDao) applicationContext.getBean("accountDao");
	    // 创建Account对象,并向Account对象中添加数据
	    Account account = new Account();
	    account.setUsername("Rose");
	    account.setBalance(1000.00);
	    // 执行addAccount()方法,并获取返回结果
	    int num = accountDao.addAccount(account);
	    if (num > 0) {
	        System.out.println("成功插入了" + num + "条数据!");
	    } else {
	        System.out.println("插入操作执行失败!");
	    }
	}
	
	@Test
	public void updateAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    AccountDao accountDao = 
	            (AccountDao) applicationContext.getBean("accountDao");
	    // 创建Account对象,并向Account对象中添加数据
	    Account account = new Account();
	    account.setId(1);
	    account.setUsername("tom");
	    account.setBalance(2000.00);
	    // 执行updateAccount()方法,并获取返回结果
	    int num = accountDao.updateAccount(account);
	    if (num > 0) {
	        System.out.println("成功修改了" + num + "条数据!");
	    } else {
	        System.out.println("修改操作执行失败!");
	    }
	}
	
	@Test
	public void deleteAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    AccountDao accountDao = 
	            (AccountDao) applicationContext.getBean("accountDao");
	    // 执行deleteAccount()方法,并获取返回结果
	    int num = accountDao.deleteAccount(1);
	    if (num > 0) {
	        System.out.println("成功删除了" + num + "条数据!");
	    } else {
	        System.out.println("删除操作执行失败!");
	    }
	}

	@Test
	public void findAccountByIdTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    AccountDao accountDao = 
	            (AccountDao) applicationContext.getBean("accountDao");
	    // 执行findAccountById()方法
	    Account account = accountDao.findAccountById(1);
	    System.out.println(account);
	}

	@Test
	public void findAllAccountTest() {
	    // 加载配置文件
	    ApplicationContext applicationContext = 
	            new ClassPathXmlApplicationContext("applicationContext.xml");
	    // 获取AccountDao实例
	    AccountDao accountDao = 
	            (AccountDao) applicationContext.getBean("accountDao");
	    // 执行findAllAccount()方法,获取Account对象的集合
	    List<Account> account = accountDao.findAllAccount();
	    // 循环输出集合中的对象
	    for (Account act : account) {
	        System.out.println(act);
	    }
	}
}
//chapter04

结果就不演示了,

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值