Spring
IOC : 使用对象的时候不手动创建,交给spring从外部中提供对象产生
外部 : 外部指的是spring中的IOC容器,用来存放Bean
Bean: 指放在外部需要创建或管理的对象,且在IOC容器中
DI : 依赖注入.在容器中有依赖关系的bean会关联绑定
XML使用
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
</dependencies>
刷新之后在resources资源下创建spring配置文件,idea右键xml创建有
注: 需要刷新导入spring-context之后才有
//配置bean
<bean id="bookdaoimpl" class="com.cdl.dao.impl.bookdaoimpl"></bean>
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");
bookServiceimpl bookServiceimpl = (com.cdl.service.impl.bookServiceimpl) app.getBean("bookServiceimpl");
bookServiceimpl.save();
}
使用DI方式解耦service层new对象
首先把new对象的代码删除,保留声明,提供set方法给bean进行绑定
接着修改spring配置文件
name指的是需要绑定的属性名名称,ref表示需要绑定的类型的bean的id,也可以绑定bean的name属性的名称
<bean id="bookdaoimpl" class="com.cdl.dao.impl.bookdaoimpl"></bean>
<bean id="bookServiceimpl" class="com.cdl.service.impl.bookServiceimpl">
<property name="bdi" ref="bookdaoimpl"></property>
</bean>
bean标签的name属性设置的是bean的别名
bean标签的scope属性设置的是单例模式或者非单例模式
默认singleton单例,可选prototype非单例
实例化bean的方式
第一种
构造方法的方式,是通过无参构造方法来进行创建,不管私有还是公共,通过反射
第二种
通过静态工厂的方式,在原先bean下设置class的值为工厂的类路径,然后需要加上factory-method参数加上方法名
第三种
使用实例工厂 的方式,先使用bean通过id和class托管实例,再加一个bean同第二种方式但是不需要class替换成factory-bean指定前面托管实例的工厂bean
第四种
是第三种的改良,通过实现FactoryBean实现方法,第一个方法getObject返回需要构建的new UserDaoImpl第二个返回类型就返回UserDao.class,通过实现isSingleton方法return true 默认true单例
生命周期控制
在bean托管的类种定义init和destory方法,然后在bean标签上增加init-method和destory-method指定方法名,默认bean销毁操作不会执行,需要我们把ApplicationContext类型转换成ClassPathXmlApplicationContext他的实现类然后进行手动.close()暴力关闭.也可以通过.registerShutdownHook()注册钩子函数来告诉虚拟机在关闭之前需要先关闭容器
定义init和destory方法也可以通过实现接口的方式这样就不用添加标签属性,实现InitializingBean和DisposableBean的afterPropertiesSet和destory方法
数据注入
引用类型前面已经使用过,使用ref来指定需要注入的属性的引用类型,且需要生成setting方法
<bean id="bookdaoimpl" class="com.cdl.dao.impl.bookdaoimpl"></bean>
<bean id="bookServiceimpl" class="com.cdl.service.impl.bookServiceimpl">
<property name="bdi" ref="bookdaoimpl"></property>
</bean>
简单类型注入,包括字符串,同样是使用property标签在bean内部,ref是引用类型注入,使用value则是简单类型注入,类型会自动转换
构造器参数注入,用的就不是property了而是constructor-arg标签指定name是形参的名称,如果是引用类型则需要ref引用bean,也可以不使用name来指定,使用index传入参数的位置0
自动装配
在bean种设置autowire参数,指定byType或者byName,指定类型装配就必须要有bean的类型一致的,按照byName的话就必须要属性名称要和id名一致,其实就是和属性的set方法去掉set把第一位变成小写,两种方式都需要生成set方法
<bean id="bdi" class="com.cdl.dao.impl.bookdaoimpl"></bean>
<bean id="bookServiceimpl" class="com.cdl.service.impl.bookServiceimpl" autowire="byName"/>
集合类型注入
格式
<bean>
<property name="">
<array><value>1</value></array>
</property>
<property name="">
<list><value>1</value></list>
</property>
<property name="">
<set><value>1</value></set>
</property>
<property name="">
<map><entry key="" value=""></entry></map>
</property>
<property name="">
<props><prop key="">1</prop></props>
</property>
</bean>
加载读取properties文件
首先需要先开启命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
// 读取,读取之后${}来读取里面的数据 ,且不加载系统的属性
<context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"></context:property-placeholder>
// 标准格式
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"></context:property-placeholder>
容器初始化方式
可添加多个用,分割
ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");
BeanFactory是IOC容器的顶层接口,初始化容器的时候,加载的bean延迟加载
ApplicationContext接口是IOC容器的核心接口,初始化容器的时候bean立即加载
注解开发
首先是需要配置xml扫描注解,先需要导入设置命名空间context
// 通过组件进行扫描
<context:component-scan base-package="com.cdl"/>
哪个类需要注入成bean就用@Component(“userDao”),可以不指定名称,但是就需要getBean中使用类.class
三个@Component衍生注解
@Controller:用于表现层bean定义
@Service: 用于业务层bean定义
@Repository: 用于数据层bean定义
作用都是一样
spring3.0开启了纯注解开发,可以使用java类来代替xml配置文件
@Configuration //声明为配置类
@ComponentScan("com.cdl") //设定扫描路径,只能一次,多个用数组
public class SpringConfig {
}
初始化容器变成AnnotationConfigApplicationContext
指定作为配置文件的类类型
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
bean生命周期函数
@PostConstruct //init
@PreDestroy //destroy
注解依赖注入
对属性需要注入的使用@Autowired注解,默认是根据类型注入,有多个就需要在指定bean声明名称就根据相同属性名查找注入
使用@Qualifier(“”)进行指定名称装配
读取properties文件内容
在配置文件类中使用
@PropertySource({"myProperties.properties"})
使用${}进行装配
@Value("${name}")
private String name;
注解管理第三方bean
比如说druid德鲁伊
直接写入在spring配置类中,定义一个方法返回手动new的配置好的连接对象,给方法加上注解@Bean
单独抽出来写一个德鲁伊配置类,同样是使用@Bean注解定义在一个方法上,说明这是一个bean
然后在spring配置类中加上
@Import(DruidConfig.class)
@Value直接给即可
第三方bean需要用到引用类型,那么就需要传入的引用类型是一个bean然后给方法加上形参,按照类型自动装配
aop
导入坐标
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
加上注解,说明用注解开发aop
@EnableAspectJAutoProxy
定义一个aop类,@Component声明bean,@Aspect遇到这个就会按照aop进行操作…代表任意参数
@Component
@Aspect
public class MyAdvice {
// 切入位置
@Pointcut("execution(* com.cdl.dao.UserDao.selectAll(..))")
public void bd(){}
public void method(){
System.out.println("共有操作");
}
}
事务
使用@Transactional注解表示开启事务,对方法添加,里面的调用不同的数据层操作加入到同一个事务中,里面不管谁在范围内出错了就都会回滚
SpringMVC
springMVC是Servlet的简化开发
入门案例
创建maven使用webapp骨架创建
导入
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
定义Controller
package com.cdl.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
// 定义bean
@Controller
public class UserController {
// 当前操作访问路径
@RequestMapping("/save")
// 设置当前返回值为响应内容
@ResponseBody
public String save(){
System.out.println("user save...");
return "{'model':'springmvc'}";
}
}
定义mvc配置类
package com.cdl.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //设置为配置
@ComponentScan("com.cdl.controller") //设置扫描路径
public class SpringMvcConfig {
}
定义加载mvc的servlet容器配置类
package com.cdl.config;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
// servlet容器启动配置类,里面加载mvc配置
public class ServletControllersInitConfig extends AbstractDispatcherServletInitializer {
// 加载mvc配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(SpringMvcConfig.class);
return applicationContext;
}
// 设置哪些请求被mvc处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 记载spring容器配置
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
运行配置maven选择toncat7:run
访问http://localhost/save 成功!
bean加载控制排除,排除注解类型Controller的类
@ComponentScan(value = "com.cdl",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
@RequestMapping(“/save”)加在类上就是整个类的所有方法的请求路径头
加在方法上就是具体路径,如果类上有那么访问方法上的就得加上前缀
get和post请求都是同样的接收
@Controller
public class UserController {
// 当前操作访问路径
@RequestMapping("/save")
// 设置当前返回值为响应内容
@ResponseBody
public String save(String name,int age){
System.out.println("user save...");
return "{'model':'springmvc'}";
}
}
遇到中文
在ServletControllersInitConfig配置类中重写getServletFilters
使用@RequestParam(“name”)可以指定请求路径方法参数的名称绑定
如果是pojo类为形参,那么对应属性名称相同的会自动传入
如果pojo类里的属性是引用类型,想要给引用类型的属性进行绑定,那么请求参数就引用类型属性名.属性名进行传参
如果形参是数组类型,相同名称的可以传递,不相同的无法传递
如果形参是集合类型比如LIst那么就需要@RequestParam注解在前面
json数据接收
请求体内
在mvc配置文件中加上@EnableWebMvc注解
请求参数注解换成@RequestBody
传递日期数据
传递的是/分隔的字符串那么就可以直接转换成Date格式形参
如果是其他格式的那么就需要使用@DateTimeFormat(pattern=“yyyy-MM-dd”)来进行修饰形参
响应
默认请求return的字符串会去找webapp下的页面响应,加上@ResponseBody注解就会响应的只是字符串
返回pojo数据的话同样加上@ResponseBody注解就会自动转换成json
需要导入这个,用于转换成json
<dependency>
<groupId>org.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>5.3.1</version>
</dependency>