tag: spring
categories: 技术

在DAO中配置JDBC 坑爹笔记

正确配置(自动装配):

1
2
@Autowired
JdbcTemplate jdbcTemplate;
1
2
3
<context:component-scan base-package="com.runsstudio.dao"/>
<context:component-scan base-package="com.runsstudio.service"/>

万万不可的配置:

1
2
ApplicationContext ioc=new ClassPathXmlApplicationContext("com/runsstudio/conf/applicationContext.xml");
JdbcTemplate jdbcTemplate=ioc.getBean("JdbcTemplate",JdbcTemplate.class)

会造成重复扫包

spring配置数据库连接池druid

连接池原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

阅读全文 »

Spring单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.runsstudio.test;


import com.runsstudio.Servlet.BookServlet;
//import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/*Spring单元测试
* 1. 导入包
* 2. @ContextConfiguration 指定配置文件位置
* 3. @RunWith指定用哪驱动进行单元测试,默认是JUnit
* @RunWith(SpringJUnit4ClassRunner.class) 使用Spring单元模块执行测试方法
* 以前@Test注解只是由JUnit执行的,现在是由Spring单元驱动的JUnit来测试的*/
@ContextConfiguration(locations = "classpath:com/runsstudio/conf/BeanAdd.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class BookTest {
// ApplicationContext ioc=new ClassPathXmlApplicationContext("com/runsstudio/conf/BeanAdd.xml");
ApplicationContext ioc=null;
@Autowired
BookServlet bookServlet;
@Test
public void test01(){
bookServlet.saveBook();
}
}

SPRING BOOT编写流程

框架编写流程:

  1. 导包

    1. 容器相关的包: beans core context expression
    2. 非WEB项目必须手动导包,并且要右键添加到web项目
    3. 除此之外还要导入一个commons-logging的日志包,没有会报错
  2. 写配置

    1. spring配置文件中,集合了IOC容器管理的所有组件

    2. 源码(src)包下,右键创建一个spring configuration文件

      image-20191128161316963

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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">
<!--注册一个Person对象,Spring自动创建这个Person对象-->
<!--
一个Bean标签可以注册一个组件、类
class: 要注册的组件的全类名
id: 这个对象的唯一标识
property 标签:给属性赋值
-->
<bean id="person01" class="com.runsstudio.bean.Person">
<property name="name" value="菜龙"/>
<property name="email" value="220@qq.com"></property>
<property name="QQ" value="1165"></property>
<property name="gender" value="male"></property>
</bean>
</beans>
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.runsstudio.test;

import com.runsstudio.bean.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class IOCTest {
/**
* 从容器中拿到组件
*/
@Test
public void testIOC(){
//ApplicationContext 代表IOC容器
//当前配置的XML配置文件在ClassPath下
//根据SPRING配置文件得到IOC对象

ApplicationContext ioc=new ClassPathXmlApplicationContext("IOCTest.xml");
Person person01 =(Person) ioc.getBean("person01");
System.out.println(person01);
}
}

结果:Person{name=’菜龙’, email=‘220@qq.com‘, QQ=1165, gender=’male’}

我们没有创建对象,但是却获取了对象

存在的几个问题:

  • src 源码包开始的路径:称为类路径的开始

    • (非WEB项目)所有源码包里的东西都会合并放在类路径里面;
    • java:/bin/
    • (WEB项目)/WEB-INF/classes 是类路径的开始
  • 导入包必须5个一起导

  • 先导包在创建配置文件

  • Spring容器接管了xml文件之后,xml文件会有一个小叶子 不然是没有的

  • 几个细节:

    • ApplicationContext(IOC容器的接口) 有两个儿子,一个是ClassPathXmlApplicationContext 表示XML文件配置文件在类路径下,另一个是FileSystemXmlApplicationContext(“f://IOC.xml”),表示XML文件配置在文件系统下

    • XML文件最好是放在src路径下,不要和bean放一起

    • Bean的对象是什么时候创建好的?new ClassPathXmlApplicationContext,创建容器的时候创建的,所以不用等到get的时候再创建对象

    • 由于上面的特性,使用同一个组件,获取两次容器的对象,获取的地址是一样的,也就是说,同一个组件在IOC容器中是单实例的

    • 如果要获取不存在的对象,比如Person person01 =(Person) ioc.getBean(“person21”); 会报org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘person21’ available

    • 最后一个细节,用property赋值一定是调用getter setter来赋值的

    • javaBean的属性名是由什么决定的?getter setter,首字母小写就是属性名

SPRING

SPRING发展

最新方法:使用JAVA配置取代XML

最核心的注解:

  • @Configuration,作用在类上,相当于一个xml配置文件

  • @Bean 作用在方法上,相当于xml配置中的

使用注解配置spring 实现IOC功能

阅读全文 »

23 测试泛型依赖注入(请参考Annotation Example)

首先要记得导包 导入

spring-aop-5.2.0.RELEASE

注入组件的时候,泛型是参考的标准!

18 @Autowired 实现根据类型实现自动装配

BookServlet

1
2
3
4
5
6
7
8
9
10
@Controller
public class BookServlet {
@Autowired
private BookService bookService;
public void saveBook(){

System.out.println("调用Servlet...");
bookService.saveBook();
}
}

BookService

1
2
3
4
5
6
7
8
9
10
@Service
public class BookService {
@Autowired
private BookDao bookDao;
public void saveBook(){
System.out.println("调用service....");
bookDao.saveBook();
}
}

BookDao

1
2
3
4
5
6
7
8
9
@Repository()
//@Scope("prototype")
public class BookDao
{
public void saveBook(){
System.out.println("调用DAO,保存了一本图书");
}
}

XML

1
<context:component-scan base-package="com.runsstudio" use-default-filters="true"></context:component-scan>

调用Servlet…
调用service….
调用DAO,保存了一本图书

只需要@Autoware 然后就再也不需要new啦!

Autoware原理:

@Autowired 首先看属性的类型,比如说

1
2
@Autowired
private BookDao bookDao;
  1. 首先找到对应组件。对应的java代码是ioc.getBean(BookService);

  2. 如果没找到,抛出No such bean exception

  3. 如果找到多个(比如说有继承关系的子类),继续找,顺序是:

    1. 成员变量名作为id继续匹配

      1. 匹配上?装配
      2. 没有匹配?报错:原因是按照变量名作为ID继续匹配的 可以使用@Qualifier(“”)指定一个新名字作为ID避免成员变量名作为id继续匹配,找不到时候的报错!

15 spring给DAO SERVICE SERVLET注解

1
2
3
4
5
6
<!--Spring有四个注解:
都能把组件添加到IOC的容器管理中
@Controller(推荐给控制器层组件加这个(Servlet))
@Service:业务逻辑,推荐给业务逻辑层组件添加这个注解
@Repository:仓库,给数据库层(DAO层,持久化层)添加这个注解
@Component:组件层,给不属于上述三层的添加这个注解,-->

使用注解将组建快速加到容器中,需要几步:

  1. 给要天天加的组件上标四个注解的任何一个

  2. 告诉Spring自动扫描加了注解的组件:依赖名称空间进行扫描,默认是单例的

    <context:component-scan base-package="com.runsstudio"></context:component-scan>

  3. 注意需要先添加命名空间

  4. 指定base-package,该包下面的所有注解类自动扫描进IOC容器。

  5. 如果要支持用注解导入组件,一定要导入AOP包(spring-aop-5.2.0.RELEASE),支持注解模式

  6. 从组件中加入的和从包中加入的,行为都是一样的

com.runsstudio 及下面所有加了注解的类都会被扫描

BeanDefinitionStoreException这里可能会包一个错误

1
2
3
4
5
6
7
8
    @Test
public void test01(){
// ID默认就是类名首字母小写
Object bookDao = ioc.getBean("bookDao");
Object bookDao2 = ioc.getBean("bookDao");
Object bookServlet = ioc.getBean("bookServlet");
System.out.println(bookDao==bookDao2);//true
}
1
@Repository("bookDaoheihei") // 指定新的 bookDao名字
1
@Scope("prototype") //指定是多实例的

由于可以用注解快速配置, XMLbean配置的方法适用于配置其他人写的包(无法修改java代码)

16/17 扫描时候只要/排除的组件

1
2
3
<context:exclude-filter type="(排除的规则)" expression=""/>
比如 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
表示不扫描 Controller

【掌握】

assignalble 全类名

annotation 注解排除

【了解】

aspectJ aspectJ表达式

custom 自定义代码特定决定哪些自己使用

regex 正则表达式

1
<context:component-scan base-package="com.runsstudio" use-default-filters="false">    <context:include-filter type="custom" expression="org.springframework.stereotype.Controller"/></context:component-scan>

注意 使用include的时候要禁用掉默认的规则use-default-filters=”false”

@Autowired @Resource @Inject 都是用来自动装配的,但是第一个最强大

@Autowired Spring

@Resource J2EE,是JDK的标准

@Inject

三个都是JAVA的标准,不过是开发公司不同

Resource 扩展更强:如果切换成另外一个容器框架,Resource还是可以使用的,Autowired 是Spring开发,离开Spring就不能用了

13 基于XML的自动装配(自定义类型的自动赋值)

​ javaBean(基本类型)

(自定义类型的属性是一个对象,这个对象在容器中可能存在)

1
2
3
4
5
6
<bean id="car" class="com.runsstudio.bean.Car">
<property name="carName" value="1"></property>
</bean>
<bean id="person" class="com.runsstudio.bean.Person">
<property name="car" ref="car"></property>
</bean>
1
2
Person bean = ioc.getBean(Person.class);
System.out.println(bean);

输出:

Person{name=’null’, email=’null’, QQ=0, gender=’null’, flag=false, car=Car{carName=’1’, price=null}, carList=null, maps=null, properties=null}

但是这里还需要一个

我们有时候不想写这么多,希望来一个自动装配,

所以有一个autowire属性

1
2
3
4
5
autowire="default"表示不自动装配
autowire="byName" 通过名字:以属性名(JAVA中的)作为id(XML中的) 去容器中找到这个组件,给他赋值
autowire="byType" 通过类型:以属性类型作为查找依据去容器中找到这个组件,如果容器中有多个该类型的组件会报错:NoUniqueBeanDefinitionException
autowire="constructor" 通过构造器:按照构造器进行赋值:如果在Person中有一个有参构造器为car赋值,则会调用该构造器赋值:先按照参数类型装配,没有就直接为组件装配null即可;如果找到了多个,装配null,参数的名作为id,继续匹配(不管怎样不会报错)

14 SpEL(Spring Expression Language)Spring表达式

在SpEL中使用字面量、引用其他bean、引用其他bean的某个属性值、调用非静态方法、调用静态方法、使用运算符

用#{}来表达

#{12*5}

#{book01.bookname}

#{car}

调用静态方法 #{T(全类名).random().toString()}

调用非静态方法 #{对象.方法名()}

12月5日 AOP(Aspect Oriented Programming)

OOP (Object Oriented Programming 面向对象编程)

面向切面编程是一种新的编程思想,AOP基于OOP,在程序运行期间,将某段代码动态地切入(插入)到指定方法的指定位置进行运行,这种编程方式称为面向切片编程。

场景:计算器运算计算方法的时候记录日志。

要加日志记录,就有非常多的方法

(1)直接编写在方法内部,这样就会变成 日志->方法->日志 的过程,修改维护麻烦,而核心功能是【业务逻辑】这种状态就是耦合

(2)也有把记录日志功能抽取出来的,LogUtils 功能

我们希望的是方法里一个代码都没有 全删掉,却保留日志功能