Spring框架入门
一、IOC容器
1、概念
IOC:Inversion of Control 控制反转
DI:Dependency Injection 依赖注入
控制反转,从字面意思来看,就是控制权又被动变主动,最后又变回被动。
举个例子:
你的主管要求你做一件事情,这个时候就存在这么几个过程:
-
主管命令你做事情(这个时候主动权在主管,你是被动的)
-
你接到命令做事情(这个时候主题是你,你是主动的,控制权在你手里)
-
你完成事情(这个时候主题依然是你,控制权在你手里)
-
报告主管做完事情(主动权又叫交到主管手里了)
-
什么是IOC
- 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
- 使用IOC目的:为了耦合度降低
- 做入门案例就是IOC实现
-
IOC底层原理
- xml解析、工厂模式、反射
2、IOC的基本应用
<!--1 set方法注入属性-->
<bean id="user" class="com.spring.pojo.User">
<!--它会调用User的set方法-->
<property name="name" value="tang"></property>
<property name="age" value="19"></property>
</bean>
<!--调用有参构造器-->
<bean id="user" class="com.spring.pojo.User">
<constructor-arg value="tang" name="name"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
<bean class="com.spring.pojo.User" id="user">
<!--null值-->
<!--<property name="name">
<null/>
</property>
<property name="age">
<value>12</value>
</property>-->
<property name="name">
<!--<value><![CDATA[<tang>]]></value>-->
<value><></value>
</property>
</bean>
<!--
set方法,bean标签进行
要先添加一个名称命名空间,如下:
xmlns:p="http://www.springframework.org/schema/p"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
-->
<bean id="user" class="com.spring.pojo.User" p:name="tang" p:age="19"></bean>
@Test
public void service() {
//创建xml的实例
ApplicationContext context = new ClassPathXmlApplicationContext("Bean2.xml");
UserService userService = (UserService) context.getBean("userService");
userService.service();
}
自动装配
` <!--自动装配:
autowire:
byName 根据名称自动装配
byType 根据类型自动装配
-->
<bean id="user" class="com.dojo.User" autowire="byType">
<property name="age" value="19"></property>
<property name="name" value="tang"></property>
</bean>
<bean id="depart" class="com.dojo.Depart" p:name="人事部门"></bean>
3、生命周期
- 生命周期
- 从对象创建到对象销毁的过程
- bean生命周期
- 通过构造器创建bean实例(无参数构造)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 调用bean的初始化的方法(需要进行配置初始化的方法)
- bean可以使用了(对象获取到了)
- 当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
<bean id="order" class="com.dojo.order" init-method="initMethod" destroy-method="destroyMethod">
<property name="order" value="tang"></property>
</bean>
<!--后置处理方法,所有对象都要经过-->
<bean id="myBean" class="com.processor.MyBeanPost"></bean>
//后置处理方法
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器的Before方法");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器的After方法");
return null;
}
}
//实例方法
public class order {
private String order;
public order(){
System.out.println("无参构造执行了");
}
public void setOrder(String order) {
System.out.println("set方法执行了");
this.order = order;
}
public void initMethod(){
System.out.println("initMethod方法执行了");
}
public void destroyMethod(){
System.out.println("destroyMethod方法执行了");
}
}
3、注入多种类型
<bean id="data" class="com.dojo.Data">
<!--int[] 类型-->
<property name="array">
<array>
<value>java基础</value>
<value>MySQL数据库基础</value>
</array>
</property>
<!--list类型-->
<property name="list" ref="booklist">
<!--<list>
<value>鸭头</value>
<value>鸭腿</value>
<value>鸭脖</value>
</list>-->
</property>
<property name="map">
<map>
<entry key="java" value="Java基础"></entry>
<entry key="MySQL" value="MySQL数据库"></entry>
</map>
</property>
<property name="set">
<set>
<value>Java</value>
<value>MySQL</value>
<value>Spring</value>
</set>
</property>
<!--向list中填入对象-->
<property name="userList">
<list>
<ref bean="user1"></ref>
<ref bean="user2"></ref>
</list>
</property>
</bean>
<!--(2)使用util标签完成list集合注入提取-->
<util:list id="booklist">
<value>易筋经</value>
<value>九阴真经</value>
<value>九阳神功</value>
</util:list>
<bean id="user1" class="com.dojo.User" p:name="tang" p:age="19"></bean>
<bean id="user2" class="com.dojo.User" p:name="lixiang" p:age="18"></bean>
4、工厂Bean(FactoryBean)
- Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)
- 普通bean:在配置文件中定义bean类型就是返回类型
- 工厂bean:在配置文件定义bean类型可以和返回类型不一样第一步创建类,让这个类作为工厂bean,实现接口FactoryBean第二步实现接口里面的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course> {//定义返回bean 要返回的类型
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
@Test
public void test3() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>
5、如何设置单实例还是多实例
- 在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
- scope属性值第一个值默认值,singleton,表示是单实例对象第二个值prototype,表示是多实例对象
<!--scope创建实例对象,单例还是多例 默认singleton:单例,proptotye : 多例-->
<bean id="myBean" class="com.factoryBean.MyBeans" scope="prototype"></bean>
二、AOP操作
1、AOP概念
(1)什么是AOP
- 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
2、动态代理
public class JDKProxy{
public static void main(String[] args) {
UserImpl userImpl = new UserImpl();
UserImplProxy implProxy = new UserImplProxy(userImpl);
//获取被代理类的所有接口
Class[] interfaces = userImpl.getClass().getInterfaces();
//加载器
ClassLoader classLoader = userImpl.getClass().getClassLoader();
UserDao proxy = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,implProxy);
int add = proxy.add(2, 7);
System.out.println(add);
}
}
class UserImplProxy implements InvocationHandler{
private Object object;
public UserImplProxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前操作,method:" + method.getName() + ",参数是:" + Arrays.toString(args));
Object invoke = method.invoke(object, args);
System.out.println("执行后操作," + object);
return invoke;
}
}
3、AOP术语
-
连接点
- 类里面的哪些方法可以被增强,这些方法称为连接点
-
切入点
- 实际被真正增强的方法
-
通知
- 实际增强
4、AOP操作
-
Spring框架一般都是基于AspectJ实现AOP操作
- AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spirng框架一起使用,进行AOP操作
-
基于AspectJ实现AOP操作
- 基于xml配置文件实现
- 基于注解方式实现(使用)
-
切入点表达式
-
切入点表达式作用:知道对哪个类里面的哪个方法进行增强
-
语法结构:execution([权限修饰符] [返回类型] [类全路径] 方法名称 )
-
举例1:对com.atguigu.dao.BookDao类里面的add进行增强execution(*com.atguigu.dao.BookDao.add(…))
-
举例2:对com.atguigu.dao.BookDao类里面的所有的方法进行增强execution(*com.atguigu.dao.BookDao.(…))
-
举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强execution(*com.atguigu.dao..*(…))
-
-
5、AOP操作(AspectJ注解)
<?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"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描注解-->
<context:component-scan base-package="com.proxy,com.dao"></context:component-scan>
<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
@Component //编译注解
@Aspect //生成代理类对象
public class UserProxy {
//@Before 表示前置通知 里面的value表示为特定
@Before(value = "execution(* com.dao.User.add(..))")
public void before(){
System.out.println("before方法执行了.....");
}
//后置通知
@After(value = "execution(* com.dao.User.add())")
public void after(){
System.out.println("after方法执行了......");
}
//后置返回通知
@AfterReturning(value = "execution(* com.dao.User.add())")
public void afterReturning(){
System.out.println("afterReturning方法执行了......");
}
//环绕通知
@Around(value = "execution(* com.dao.User.add())")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕之前......");
pjp.proceed();
System.out.println("环绕之后......");
}
//后置错误通知
@AfterThrowing(value = "execution(* com.dao.User.add())")
public void afterThrowing(){
System.out.println("AfterThrowing......");
}
}
@Component
@Aspect //生成代理类对象
public class UserProxy {
//相同切入点提取出来
@Pointcut(value = "execution(* com.dao.User.add(..))")
public void pointDom(){
}
//@Before 表示前置通知 里面的value表示为特定
@Before(value = "pointDom()")
public void before(){
System.out.println("before方法执行了.....");
}
@After(value = "pointDom()")
public void after(){
System.out.println("after方法执行了......");
}
@AfterReturning(value = "pointDom()")
public void afterReturning(){
System.out.println("afterReturning方法执行了......");
}
@Around(value = "pointDom()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕之前......");
pjp.proceed();
System.out.println("环绕之后......");
}
@AfterThrowing(value = "pointDom()")
public void afterThrowing(){
System.out.println("AfterThrowing......");
}
}
@Component
@Aspect
@Order(1) //优先级设置,越小优先级越高
public class UserOrder {
@Before(value = "execution(* com.dao.User.add())")
public void before(){
System.out.println("UserOrder的Before方法执行了...");
}
}
-
AspectJ的xml配置
首先写两个实例类
public class Book { public void add(){ System.out.println("add............."); } }
public class BookProxy { public void Before(){ System.out.println("Before..........."); } }
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="book" class="com.xmlProxy.Book"></bean> <bean id="bookProxy" class="com.xmlProxy.BookProxy"></bean> <!--配置aop增强--> <aop:config> <!--切入点--> <aop:pointcut id="p" expression="execution(* com.xmlProxy.Book.add())"/> <!--配置切面--> <aop:aspect ref="bookProxy"> <!--增强指定方法--> <aop:before method="Before" pointcut-ref="p"></aop:before> </aop:aspect> </aop:config> </beans>
测试方法
@Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml"); Book book = context.getBean("book", Book.class); book.add(); }
-
完全注解配置
@Configurable //组件扫描 @ComponentScan(value = {"com"}) //开启Aspect 生成代理类 @EnableAspectJAutoProxy(proxyTargetClass = true) public class configAop { }
测试类
@Test public void test2(){ ApplicationContext context = new AnnotationConfigApplicationContext(configAop.class); User user = context.getBean("user", User.class); user.add(); }
三、JdbcTemplate
1、xml配置
<context:component-scan base-package="com.dao,com.service"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
<!--创建JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
2、增加操作
@Service
public class BookService {
@Autowired
private BookDao bookDao;
//添加操作
public int addBook(Book book){
return bookDao.add(book);
}
}
//BookTest类
public class BookTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book(null,"java基础","tang");
int i = bookService.addBook(book);
System.out.println(i);
}
}
//BookDaoImpl 类
@Repository
public class BookDaoImpl implements BookDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int add(Book book) {
String sql = "insert into book(id,name,author) value(?,?,?)";
return jdbcTemplate.update(sql,book.getId(),book.getName(),book.getAuthor());
}
}
3、更新与删除
//BookService
//更新书籍
public int updateBook(Book book){
return bookDao.update(book);
}
public int deleteBook(int id){
return bookDao.delete(id);
}
//BookService
@Override
public int update(Book book) {
String sql = "update book set name=?,author=? where id=?";
return jdbcTemplate.update(sql,book.getName(),book.getAuthor(),book.getId());
}
@Override
public int delete(int id) {
String sql = "delete from book where id=?";
return jdbcTemplate.update(sql,id);
}
//测试类
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book(1,"java基础","小菜鸟");
bookService.updateBook(book);
}
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
//Book book = new Book(1,"java基础","小菜鸟");
bookService.deleteBook(1);
}
4、获取数据的数量
//BookDaoImpl
@Override
public int queryCount() {
String sql = "select count(*) from book";
return jdbcTemplate.queryForObject(sql,Integer.class);
}
//BookService
//返回数据的数量
public int queryBookCount(){
return bookDao.queryCount();
}
5、获取所有数据
//BookService
@Override
public List<Book> queryAll() {
String sql = "select * from book";
return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(Book.class));
}
@Test
public void test4(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
List<Book> book = bookService.queryAllBook();
System.out.println(book);
}
6、批量操作
batchUpdate(sql,List<Object[]>)
//BookService
@Override
public void batchAdd(List<Object[]> batchArgs) {
String sql = "insert into book(id,name,author) value(?,?,?)";
jdbcTemplate.batchUpdate(sql,batchArgs);
}
//批量操作
public void batchAddBook(List<Object[]> batchArgs){
bookDao.batchAdd(batchArgs);
}
@Test
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
List<Object[]> batchArgs = new ArrayList<>();
Object[] obj1 = {3,"java高级","li"};
Object[] obj2 = {4,"jdbc","li"};
batchArgs.add(obj1);
batchArgs.add(obj2);
bookService.batchAddBook(batchArgs);
}
四、事务操作
1、事务是什么
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。
2、事务的四大特性
数据库事务 (transanction) 正确执行的四个基本要素。ACID,原子性(Atomicity)、一致性(Correspondence)、隔离性(Isolation)、持久性(Durability)。
(1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
(2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
(3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
(4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
3、消费功能
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 消费
* @param id 要消费的id
* @param count 消费的钱
*/
@Override
public void reduceMoney(int id,int count) {
String sql = "update user set money=money-? where id=?";
jdbcTemplate.update(sql,count,id);
}
@Override
public void addMoney(int id,int count) {
String sql = "update user set money=money+? where id=?";
jdbcTemplate.update(sql,count,id);
}
@Override
public int queryMoney(int id) {
String sql = "select money from user where id=?";
return jdbcTemplate.queryForObject(sql,Integer.class,id);
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 消费
* @param consumer 消费的人的id
* @param producer 生产者的id
* @param count 消费的金额
*/
public void countChange(int consumer,int producer,int count){
int money = userDao.queryMoney(consumer);
if (money >= count){
userDao.reduceMoney(consumer,count);
userDao.addMoney(producer,count);
}else {
System.out.println("余额不足...");
}
}
}
4、添加事务
用注解声明法添加事务
在service类上面(或者service类里面方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加方法上面
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务
- xml
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
- userService
@Service
@Transactional //事务注解
public class UserService {
@Autowired
private UserDao userDao;
/**
* 消费
* @param consumer 消费的人的id
* @param producer 生产者的id
* @param count 消费的金额
*/
public void countChange(int consumer,int producer,int count){
int money = userDao.queryMoney(consumer);
if (money >= count){
userDao.reduceMoney(consumer,count);
int n = 10/0;
userDao.addMoney(producer,count);
}else {
System.out.println("余额不足...");
}
}
}
5、@Transactional
public @interface Transactional {
@AliasFor("transactionManager")
String value() default ""; //可选,指定事务的事务管理器
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;//可选,事务的传播行为
Isolation isolation() default Isolation.DEFAULT; //可选,事务的隔离级别
int timeout() default -1; //事务超出时间设置
boolean readOnly() default false; //读写或只读事务,默认读写
Class<? extends Throwable>[] rollbackFor() default {}; //导致事务回滚的异常数组,可选
String[] rollbackForClassName() default {}; //导致事务回滚的异常类的名字,可选
Class<? extends Throwable>[] noRollbackFor() default {}; //不会导致事务回滚的异常数组,可选
String[] noRollbackForClassName() default {}; //不会导致事务回滚的异常类名的数组,可选
}
事务级别 | 事务名称 | 含义 |
---|---|---|
Read uncommitted | 脏读 | 就是一个事务可以读取另一个未提交事务的数据 |
Read committed | 不可重复读 | 就是一个事务要等另一个事务提交后才能读取数据。 |
Repeatable read | 幻读 | 重复读,就是在开始读取数据(事务开启)时,不再允许修改操作 |
Serializable | 串行化读,事务只能一个一个执行,效率慢 |
脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。
事物的传播类型 | 说明 |
---|---|
REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
SUPPORTS | 支持当前事务,如果没有当前事务,就以非事务方法执行。 |
MANDATORY | 使用当前事务,如果没有当前事务,就抛出异常。 |
REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
NEVER | 以非事务方式执行操作,如果当前事务存在则抛出异常。 |
NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作 |
mandatory(强制性的 )
@Service
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED)
//事务注解
public class UserService {
@Autowired
private UserDao userDao;
/**
* 消费
* @param consumer 消费的人的id
* @param producer 生产者的id
* @param count 消费的金额
*/
public void countChange(int consumer,int producer,int count){
int money = userDao.queryMoney(consumer);
if (money >= count){
userDao.reduceMoney(consumer,count);
int n = 10/0;
userDao.addMoney(producer,count);
}else {
System.out.println("余额不足...");
}
}
}
6、xml配置事务
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--配置事务参数-->
<tx:advice id="txAdvice">
<tx:attributes>
<!--制定哪种方法上添加事务-->
<tx:method name="countChange" propagation="REQUIRED"/>
<!--<tx:method name="count*"/>-->
</tx:attributes>
</tx:advice>
<!--设置切入点和切面-->
<aop:config>
<!--切入点-->
<aop:pointcut id="pt" expression="execution(* com.service.UserService.*(..))"/>
<!--设置切面-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
7、完全注解开发
@Configurable //配置类
@ComponentScan(basePackages = "com") //组件扫描
@EnableTransactionManagement //开启事务
public class UserConfig {
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/person");
dataSource.setUsername("root");
dataSource.setPassword("123");
return dataSource;
}
//创建jdbcTemplate 对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager manager =
new DataSourceTransactionManager();
manager.setDataSource(dataSource);
return manager;
}
}
@Test
public void countChange1(){
ApplicationContext context =
new AnnotationConfigApplicationContext(UserConfig.class);
UserService userService =
context.getBean("userService", UserService.class);
userService.countChange(1,2,100);
}
五、spring5的新特性
1、log4j2
需要的包
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="DEBUG">
<!--先定义所有的appender-->
<appenders>
<!--输出日志信息到控制台-->
<console name="Console" target="SYSTEM_OUT">
<!--控制日志输出的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
public class Log4J {
private static final Logger log = LoggerFactory.getLogger(Log4J.class);
public static void main(String[] args) {
log.warn("\nlog4J Hello\n");
log.info("\nlog4J Hello\n");
}
}
2、@Nullable 注解
@Nullable 注解可以使用在方法、属性、参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空
3、函数式编程
GenericApplicationContext
//函数式编程,交给spring处理
public class GenericApplicationContextTest {
public static void main(String[] args) {
//创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//调用context对象的方法注册
context.refresh();
context.registerBean("user", User.class,()->new User("tang"));
//获取对象的方法
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
4、测试类
JTest4
@RunWith(SpringJUnit4ClassRunner.class) //加载单元测试类的框架
@ContextConfiguration("classpath:bean1.xml") //加载配置文件
public class SpringTest {
@Autowired
private UserService userService;
@Test
public void test(){
userService.countChange(1,2,100);
}
}
JTest5
//@ExtendWith(SpringExtension.class) //JTest5操作
//@ContextConfiguration("classpath:bean1.xml")
@SpringJUnitConfig(locations = "classpath:bean1.xml") //复合注解,等同于上面个两个
public class JTest5 {
@Autowired
private UserService userService;
@Test
public void test(){
userService.countChange(1,2,100);
}
}
//创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//调用context对象的方法注册
context.refresh();
context.registerBean("user", User.class,()->new User("tang"));
//获取对象的方法
User user = context.getBean("user", User.class);
System.out.println(user);
}
}