Spring学习笔记(基于Idea,maven)
耦合: 程序间的依赖关系.在开发中,应该做到解决编译期依赖,即编译期不依赖,运行时才依赖.
解耦的思路: 使用反射来创建对象,而避免使用new关键字,并通过读取配置文件来获取要创建的对象全限定类名.
IOC(控制反转)
pom.xml
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
</dependencies>
<?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.xsd">
<!--把对象的创建交给spring来管理 -->
<!--第一种创建Bean的方式 -->
<!--将UserServiceImpl 加载进spring容器 -->
<bean id="userServiceImpl" class="com.cgx.service.impl.UserServiceImpl" >
</bean>
<!--将UserDaoImpl 加载进spring容器 -->
<bean id="userDaoImpl" class="com.cgx.dao.impl.UserDaoImpl">
</bean>
<!--第二种创建Bean的方式 -->
<!--将userFactory 工厂加载进spring容器 -->
<bean id="userFactory" class="com.cgx.service.factory.userFactory" >
</bean>
<!--通过userFactory工厂将userService加载进spring容器
factoty-bean:指定那个bean的id来创建
factory-method:指定那个方法名称来创建
-->
<bean id="userService" factoty-bean="userFactory" factory-method="getUsetService">
</bean>
<!--第三种创建Bean的方式 使用工厂中的静态方法-->
<bean id="userService" class="com.cgx.factory.UserFactory"
factorymethod="getUserService2"></bean>
</beans>
public static void main(String[] args) {
//获取spring核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//根据id获取bean对象
UserService us = (UserService) ac.getBean("userServiceImpl");
UserDao ud = ac.getBean("userDaoImpl", UserDao.class);
System.out.println(us);
System.out.println(ud);
}
ApplicationContext接口的注意事项
ApplicationContext接口的实现类中我们常用的容器有三种:
ClassPathXmlApplicationContext:它是从根目录下加载配置文件
FileSystemXmlApplicationContext:它是从磁盘路径下加载配置文件
AnnotationConfigApplicationContext:读取注解创建容器
ApplicationContext接口 单例对象使用
他在构建核心容器时,创建对象采取的策略是立即加载的方式。只要一读取玩配置文件就会创建配置文件中配置的对象
**Beanfactory接口 ** 多例对象使用
他在构建核心容器时,创建对象采取的策略是延迟加载的方式。什么时候根据id获取对象了,什么时候才创建对象
bean标签的属性
- 作用: 配置托管给spring的对象,默认情况下调用类的无参构造函数,若果没有无参构造函数则不能创建成功
- 属性:
id
: 指定对象在容器中的标识,将其作为参数传入getBean()
方法可以获取获取对应对象.class
: 指定类的全类名,默认情况下调用无参构造函数- scope: 指定对象的作用范围,可选值如下
singleton
: 单例对象,默认值prototype
: 多例对象request
: 将对象存入到web项目的request域
中session
: 将对象存入到web项目的session域
中global session
: 将对象存入到web项目集群的session域
中,若不存在集群,则global session
相当于session
init-method
:指定类中的初始化方法名称,在对象创建成功之后执行destroy-method
:指定类中销毁方法名称,对prototype
多例对象没有作用,因为多利对象的销毁时机不受容器
控制
Bean的生命周期
单例对象
出生:容器创建时对象出生
活着:只要容器还在对象一直活着
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例对象
出生:当我们使用对象是spring框架为我们创建
活着:对象只要在使用过程中就一直活着
死亡:当对象尝试不用,且没有对象引用时,由java的垃圾回收器来回收
DI(依赖注入)
在当前类需要其他类的对象时,由spring为我们提供,我们只需要在配置文件中说明
依赖关系的维护就称之为依赖注入
能注入三种类型:
① 基本类型和String
② 其他bean类型(在配置文件中或注解配置过的)
③ 复杂类型和集合类型
注入的三种方式
①set注入
在bean标签的内部使用 property 标签
标签的属性:
name:用于指定给构造函数的指定名称的参数赋值
value:用于提供基本数据类型和string类型的数据
ref:用于指定其他bean的类型数据。他指的就是在spring中IOC核心容器中出现过的bean对象
bean.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.xsd">
<!-- set注入-->
<bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
<property name="name" value="翠花"></property>
<property name="age" value="45"></property>
<property name="birthday" ref="date"></property>
</bean>
<!-- 使用spring管理创建对象并加入容器-->
<bean id="date" class="java.util.Date"></bean>
</beans>
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println("account save ..............."+name+age+birthday);
}
}
测试类
public class UserController {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
AccountService as = ac.getBean("accountService", AccountService.class);
as.saveAccount();
}
}
运行结果
“C:\Program Files\Java\jdk1.8.0_73\bin\java.exe”
[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …翠花45Wed Jul 29 17:01:31 CST 2020
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.028 s
[INFO] Finished at: 2020-07-29T17:01:31+08:00
[INFO] ------------------------------------------------------------------------
复杂和集合类型注入
用于给list结构注入的标签:
list set array
用于给map 结构注入的标签:
map props
节构相同标签可以互换
bean.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.xsd">
<bean id="arrayService" class="com.cgx.service.impl.ArrayServiceImpl">
<property name="str">
<array>
<value>AAA</value>
</array>
</property>
<property name="list">
<list>
<value>AAA</value>
</list>
</property>
<property name="set">
<set>
<value>AAA</value>
</set>
</property>
<property name="map">
<map>
<entry key="aaa" value="AAA"></entry>
</map>
</property>
<property name="property">
<props>
<prop key="aaa">AAA</prop>
</props>
</property>
</bean>
</beans>
ArrayServiceImpl.java
public class ArrayServiceImpl implements ArrayService {
private String[] str;
private List<String> list;
private Set<String> set;
private Map<String ,String> map;
private Properties property;
public void setStr(String[] str) {
this.str = str;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperty(Properties property) {
this.property = property;
}
@Override
public void test() {
System.out.println(Arrays.toString(str));
System.out.println(set);
System.out.println(list);
System.out.println(map);
System.out.println(property);
}
}
测试类
public class UserController {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
AccountService as = ac.getBean("accountService", AccountService.class);
as.saveAccount();
ArrayService ass = ac.getBean("arrayService", ArrayService.class);
ass.test();
}
}
运行结果
[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …翠花45Wed Jul 29 17:49:29 CST 2020
[AAA]
[AAA]
[AAA]
{aaa=AAA}
{aaa=AAA}
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.748 s
[INFO] Finished at: 2020-07-29T17:49:29+08:00
[INFO] ------------------------------------------------------------------------
②构造器注入
在 bean 标签的内部使用 constructor-arg 标签来注入
标签的属性
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个后某些参数的构造类型
index:用于指定要注入数据给构造函数中指定索引的位置参数,从0开始
name:用于指定给构造函数的指定名称的参数赋值
以上三个标签是给构造函数赋值的======
value:用于提供基本数据类型和string类型的数据
ref:用于指定其他bean的类型数据。他指的就是在spring中IOC核心容器中出现过的bean对象
优势:
在获取bean对象时,注入的数据是必须的操作,否则对象无法创建成功
弊端:
改变了bean对象的实例化方式,使我们在穿件对象时,用不到这些对象时,页必须提供
bean.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.xsd">
<bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="date"></constructor-arg>
</bean>
<bean id="date" class="java.util.Date"></bean>
</beans>
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
@Override
public void saveAccount() {
System.out.println("account save ..............."+name+age+birthday);
}
}
main方法
public class UserController {
int id;
public static void main(String[] args) {
//获取核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//根据id获取bean对象
AccountService as = ac.getBean("accountService", AccountService.class);
as.saveAccount();
}
}
运行结果
[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …张三18Wed Jul 29 16:38:30 CST 2020
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.791 s
[INFO] Finished at: 2020-07-29T16:38:30+08:00
[INFO] ------------------------------------------------------------------------
③ 注解注入
spring的常用注解
使用注解配置的方式实现IOC
用于创建对象的
他们的作用就和bean标签的实现的功能是一样的
使用前提: 需要在bean.xml中配置扫描的包
@Component【(“accountService”) 】
作用:用于把当前类加载到spring容器
属性:value 用于指定配置bean的id。当我们不写时默认为当前类的首字母小写
@Controller:用于表现层
@Service:用于业务层
@ Repository:用于持久层
以上三个注解和@Component作用是一样的
bean.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启扫描注解 -->
<context:component-scan base-package="com.cgx"/>
</beans>
AccountServiceImpl.java
@Component("accountService")
public class AccountServiceImpl implements AccountService {
@Override
public void test() {
System.out.println("service test() Execute.........");
}
}
main方法
public class Client {
public static void main(String[] args) {
//获取spring核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据id获取bean对象
AccountService as = ac.getBean("accountService", AccountService.class);
as.test();
}
}
用于注入数据的
@Autowired
作用:自动按照类型注入。只要容器中有唯一 一个bean对象类型和要注入的类型匹配,就可以注入成功。
如果IOC容器中没有任何bean的类型的类型和要注入的变量类型相匹配,则报错。
如果IOC容器中有多个类型时,如图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyWsedtp-1596699794005)(D:\杂物\Typora笔记文档\image\image-20200730162814109.png)]
位置: 可以是变量上也可以是方法上
@Qualifier(“accountDaoImpl”)
作用:在按照类中注入的基础之上再按名称注入,不能单独使用,但是在个方法参数注入是可以。
属性:value:用于指定注入bean的id
@Resource【(name=“accountDaoImpl”)】
作用:直接按照bean的id注入。他可以独立使用。
属性:name:用于指定bean的id。注入的接口只有一个实现类是可以不写。
以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
另外集合类型的注入只能通过XMl来实现
用于于改变他们作用范围的
@Scope
他的作用就和bean标签中scope属性实现的功能是一样。
作用:指定bean的作用 范围
属性: value:指定范围的取值。常用的取值: singleton prototype
和生命周期相关的
作用就和在bean标签中使用init-methode和destroy-methode的作用是一样。
PreDestroy
用于指定销毁方法
PostConstruct
用于指定初始化方法
基于dbutils案例
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Spring_Demo_02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
Accountdao AccountService
public interface AccountDao {
//查询
List<Account> findSelectAll();
//查询单个
Account findById(int id);
//添加
void addAccount(Account account);
//修改
void updateAccount(Account account);
//删除
void deleteAccount(int id);
}
AccountServiceImpl
@Component
public class AccountServiceImpl implements AccountService {
@Resource(name="accountDaoImpl")
private AccountDao accountDao;
@Override
public List<Account> findSelectAll() {
return accountDao.findSelectAll();
}
@Override
public Account findById(int id) {
return accountDao.findById(id);
}
@Override
public void addAccount(Account account) {
accountDao.addAccount(account);
}
@Override
public void updateAccount(Account account) {
accountDao.updateAccount(account);
}
@Override
public void deleteAccount(int id) {
accountDao.deleteAccount(id);
}
}
AccountDaoImpl
@Repository
public class AccountDaoImpl implements AccountDao {
@Resource
private QueryRunner qr;
@Override
public List<Account> findSelectAll() {
try {
return qr.query("select * from account",
new BeanListHandler<Account>(Account.class));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Account findById(int id) {
try {
return qr.query("select * from account where id= ?", new BeanHandler<Account>(Account.class),id);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void addAccount(Account account) {
try {
qr.update("insert into account set name = ?, money = ?",
account.getName(),
account.getMoney());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void updateAccount(Account account) {
try {
qr.update("update account set name = ?, money=? where id = ?",
account.getName(),account.getMoney(),account.getId());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void deleteAccount(int id) {
try {
qr.update("delete from account where id = ?", id);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
bean.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描包 -->
<context:component-scan base-package="com.cgx"/>
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
<!--引入数据源 -->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!-- 配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接信息-->
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
测试
public class Client {
public static void main(String[] args) {
//获取spring核心容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//根据id获取bean对象
AccountService as = ac.getBean("accountServiceImpl", AccountService.class);
System.out.println(as.findSelectAll());
// System.out.println(as.findById(3));
// Account account = new Account();
// account.setMoney(1200f);
// account.setName("FFF");
// as.addAccount(account);
// as.deleteAccount(4);
// Account account = new Account();
// account.setId(5);
// account.setMoney(1200f);
// account.setName("GGG");
// as.updateAccou配置nt(account);
}
}
使用注解实现配置(了解)
创建一个配置类,他的作用和bean.xml是一样
@Configuration
作用:表示当前类是一个配置类
位置:放到类名的最上方
@ComponentScan(“com.cgx”)
作用:通过该注解可以指定spring创建容器时要扫描的包
位置:放到类名的上方
属性: value:他和basePackages 的作用是一样指定spring创建容器时要扫描的包
相当于: <context:component-scan base-package=“com.cgx”/>
@Bean(“xx”)
作用:用于把当前方法的返回值作为bean对象存入spring的IOC容器中
属性: name:用于指定bean的id,当不写时,默认值是方法名
细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有的可用的bean对象。 查找的方式和Autowirte一样 。
ConfigSpring.java
@Configuration
@ComponentScan("com.cgx")
public class ConfigSpring {
/**
* 创建一个返回QueryRunner的方法
* @param dataSource
* @return
*/
@Bean("qr")
public QueryRunner getQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name = "dateSource")
@Scope("prototype")
public DataSource getDaoSource(){
try {
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
cpds.setUser("root");
cpds.setPassword("root");
return cpds;
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
}
}
测试类
public class Client {
public static void main(String[] args) {
//获取spring核心容器
ApplicationContext ac =
new AnnotationConfigApplicationContext(ConfigSpring.class);
//根据id获取bean对象
AccountService as = ac.getBean("accountServiceImpl", AccountService.class);
System.out.println(as.findSelectAll());
}
}
动态代理回顾
特点: 字节码随用随创建,随用随加载
作用:不修改源码的基础上对方法增强
分类:①基于接口 ② 基于类
基于接口的动态代理
涉及的类:Proxy
提供者:JDK官方
如何创建代理对象:使用Proxy类中的静态方法newProxyIntance
要求:被代理类至少实现一个接口。没有不能使用
newProxyIntance()的参数
ClassLoader :他是用于加载对象字节码的,和被代理对象使用相同类型的加载器。固定写法。
Class<?>[] :字节码数组,他是用于代理对象和被代理对象有相同的方法。固定写法。
InvocationHandler:用于提供增强的代码,他是让我们写如何代理,我们一般都是一些该接口的实现类,同城情况下都是匿名内部类,但不是必须的。此接口的实现类都是谁用谁写。
方法参数含义:proxy 代理对象的引用 method:当前执行的方法 args:当前执行方法所需要的参数 返回和被代理对象方法有相同的返回值。
AOP面向切面
通过动态代理的方式实现。
Spring基于xml配置AOP
把通知bean也交给spring来管理
使用 aop:config 标签表名开始AOP的配置
使用 aop:aspect标签表明配置切面
id:是给切面提供唯一标识
ref:是指定通知类bean的Id
在 aop:aspect标签内部使用对应的标签来配置通知类型
aop:berfore:表示配置前置通知
method:用于指定通知类中那个方法是前置通知
pointcut:用于指定切入点表达式,该表达式的含义是对指定方法增强
切入点表达式的写法:
关键字:execution(“表达式”)
表达式写法
public void com.cgx.service.impl.AccountServiceImpl.saveAccont();
访问修饰符可以省略
void com.cgx.service.impl.AccountServiceImpl.saveAccont();
返回值类型可以使用通配符
* com.cgx.service.impl.AccountServiceImpl.saveAccont();
//包名可以使用通配符 * *.*.*.*.*.saveAccount(); //类名和方法名也能使用通配符 * *.*.*.*.AccountServiceImpl.saveAccount(); * *.*.*.*.*.*(); * *..*.*(); //参数列表 /** *可以直接写数据类型 * 基本数据类型直接写 int * 引用数据类型写包名.类名 java.lang.String * 可以使用通配符表示任意参数类型,但是必须要参数 * 可以使用..表示,有无参数均可 */ //全统配写法 * *..*.*(..); //常用写法 * com.cgx.service.impl.*.*(..)
案例
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Spring_Demo_03</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
AccountServieImpl.java
package com.cgx.service.impl;
import com.cgx.service.AccountService;
public class AccountServiceImpl implements AccountService {
@Override
public void saveAccount() {
System.out.println("saveAccount execute......");
}
@Override
public void updateAccount(int i) {
System.out.println("updateAccount execute......"+i);
}
@Override
public int deleteAccount() {
System.out.println("deleteAccount execute......");
return 0;
}
}
Logges
package com.cgx.utils;
public class Logges {
public void berfor(){
System.out.println("前置通知执行了");
}
}
bean.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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="log" class="com.cgx.utils.Logges"></bean>
<bean id="accountServiceImpl" class="com.cgx.service.impl.AccountServiceImpl"></bean>
<aop:config>
<aop:aspect id="loge" ref="log">
<aop:before method="berfor" pointcut="execution(* com..AccountServiceImpl.*(..))"></aop:before>
</aop:aspect>
</aop:config>
<!--
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.cgx.service.impl.*.*(..))"/>
<aop:aspect id="loge" ref="log">
<aop:before method="berfor" pointcut-ref="pointcut"></aop:before>
</aop:aspect>
</aop:config>-->
</beans>
测试类
import com.cgx.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
@Test
public void test01(){
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
AccountService as = ac.getBean("accountServiceImpl",AccountService.class);
as.saveAccount();
as.deleteAccount();
as.updateAccount(1);
}
}
结果
前置通知执行了
saveAccount execute…
前置通知执行了
deleteAccount execute…
前置通知执行了
updateAccount execute…1
Spring中JdbcTemplate
他是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装。
JdbcTemplate使用的简单案例
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Spring_Demo_03</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
bean.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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dmd"></property>
</bean>
<!--配置数据源 -->
<bean id="dmd" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>
测试类
package com.cgx.jdbcTemplate;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class TemplateSpring {
// @Test
// public void test(){
// DriverManagerDataSource dmd = new DriverManagerDataSource();
// dmd.setDriverClassName("com.mysql.jdbc.Driver");
// dmd.setUrl("jdbc:mysql://localhost:3306/test");
// dmd.setUsername("root");
// dmd.setPassword("root");
//
// JdbcTemplate jdbcTemplate = new JdbcTemplate(dmd);
// jdbcTemplate.update("insert into account set name='QQQ',money=1000");
// }
@Test
public void test2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
jdbcTemplate.execute("insert into account set name='EEE',money=1000");
List<Account> accounts = jdbcTemplate.query("select * from account",
new BeanPropertyRowMapper<Account>(Account.class));
accounts.stream().forEach(account -> System.out.println(account));
}
}
基于xml的aop事务控制
事务控制是基于业务层的。
①配置数据源
属性:
id:指定唯一标识 、(dataSource)
class:由spring提供的数据源 (可以使用其他数据源)
org.springframework.jdbc.datasource.DriverManagerDataSource
set注入:
数据库连接驱动 、 URL、 用户名、密码
②配置事务管理器
id:指定唯一标识
class:spring提供的事务管理器
org.springframework.jdbc.datasource.DataSourceTransactionManager
set注入数据源
id:DataSourceTransactionManager的方法setDataSource(dataSource)
ref:配置的数据源的id
③配置事务通知
id:指定唯一标识
transaction-manage:指定事务管理器的id
配置事务增强
< tx:attributes>
< tx:method >中的属性 name:增强的方法
propagation=“REQUIRED” 事务的隔离级别
read-only="false"是否只读
④配置aop
配置切入点表达式
配置事务通知和切入点表达式的连接
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/tx/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<bean id="accountDao" class="com.cgx.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 导入db.properties文件
<context:property-placeholder location="classpath:db.properties" />
-->
<!--配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务增强 -->
<tx:attributes>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED" read-only="false"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--配置aop-->
<aop:config>
<!--配置切入点表达式
<aop:pointcut id="pointcut"
expression="execution(* com.cgx.service.impl.*.*(..))"/>
-->
<!--配置事务通知和切入点表达式的连接 -->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.cgx.service.impl.*.*(..))"/>
</aop:config>
</beans>
anagerDataSource">
<!--配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务增强 -->
<tx:attributes>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED" read-only="false"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--配置aop-->
<aop:config>
<!--配置切入点表达式
<aop:pointcut id="pointcut"
expression="execution(* com.cgx.service.impl.*.*(..))"/>
-->
<!--配置事务通知和切入点表达式的连接 -->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.cgx.service.impl.*.*(..))"/>
</aop:config>
```