Spring
控制反转IOC(Inversion of Control)
- 使用对象时,有主动new产生对象转为外部提供对象,对象控制权由程序转移到外部,此思想称为控制反转。
IOC就是上面所提到的“外部”,管理大量的对象,负责对象的创建、初始化等一系列工作,被创建或者被管理的对象在IoC容器中称为Bean
依赖注入DI(Dependency InJection)
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为以来注入。(比如service和dao之间的依赖关系)
目标:充分解耦
使用的时候不单可以直接从IoC容器中获取,而且获取到的bean已经绑定了所有的依赖关系。
IOC快速入门##
service层
BookService
package com.itheima.service;
public interface BookService {
void save();
}
BookServiceImpl
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
BookDao bookDao=new BookDaoImpl();
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
Dao层
BookDao
package com.itheima.dao;
public interface BookDao {
public void save();
}
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save...");
}
}
主方法App
package com.itheima;
import com.itheima.service.BookService;
import com.itheima.service.impl.BookServiceImpl;
public class App {
public static void main(String[] args) {
System.out.println("111");
}
}
运行之后控制台显示
book service save ...
book dao save...
下面开始用spring的文件
在pom.xml里面添加坐标
新建一个applicationContext.xml
主方法里面
package com.itheima;
import com.itheima.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) applicationContext.getBean("bookService");
bookService.save();
}
}
会发现,此时控制台也输出了和前面一样的结果。
DI入门(XML版)
- 基于上面的IoC管理bean
- Service中使用new的形式不能保留
- Service中需要的Dao对象如何进入到Service中?提供方法
- Service和Dao的关系如何描述?用配置
在BookServiceImpl中删除new形式创建对象,增加一个设置bookDao的方法
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
// BookDao bookDao=new BookDaoImpl();删除该方法的new形式
private BookDao bookDao;
//创建一个新的方法设置bookDao
public void setBookDao(BookDao bookDao){
this.bookDao=bookDao;
}
public void save(){
System.out.println("book service save ...");
bookDao.save();
}
}
在applicationContext中配置bean之间的关系
在property标签中
name表示配置哪一个属性,这里是BookServiceImpl中的bookDao属性 (private BookDao bookDao;)
ref表示参照的是哪个bean,值是其他bean的id,这里显示的就是bookDao的bean的id
运行发现,结果能达到一样的效果
bean的配置↓
别名
- bean标签可以用name来设置别名,可以用逗号、分号或者空格来隔开设置多个别名
- bean和bean之间也可以用别名引用
spring默认给我们创造的bean是单例吗?
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService1 = (BookService) applicationContext.getBean("bookService");
BookService bookService2 = (BookService) applicationContext.getBean("bookService");
System.out.println(bookService1);
System.out.println(bookService2);
}
}
运行结果是
com.itheima.service.impl.BookServiceImpl@25bbe1b6
com.itheima.service.impl.BookServiceImpl@25bbe1b6
可以看到获取到的默认是同样的对象,即证明是单例,如果需要创建非单例怎么创建呢?
我们可以去配置类applicationContext.xml中的bean标签里添加scope属性
再次运行结果,发现已经变成了两个对象
com.itheima.service.impl.BookServiceImpl@25bbe1b6
com.itheima.service.impl.BookServiceImpl@5702b3b1
scope的属性:
- "prototype"非单例
- "singleton"单例(默认)
这里就体现了spring的优点,默认为单例,提高bean内容的复用性,不用像曾经一样,用一次new一个对象。但是有不适用单例的情况,比如说封装的实体类对象,因为每次数据不一样,所以不能重用。
bean实例化(构造方法.常用)↓
bean本质上就是对象,创建bean是使用无参的构造方法完成的
在BookDaoImpl中添加无参构造方法
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save...");
}
//new↓
public BookDaoImpl() {
System.out.println("bookdao Construct!!!");
}
}
运行后会发现无参构造方法中的语句运行了。就算是设置为private私有的构造方法也能访问,说明其是通过反射实现。
bean实例化(静态工厂实例化bean.了解)↓
创建好 OrderDao和实现类OrderDaoImpl、OrderDaoFactory。
OrderDao
package com.itheima.order;
public interface OrderDao {
void save();
}
OrderDaoImpl
package com.itheima.order.impl;
import com.itheima.order.OrderDao;
public class OrderDaoImpl implements OrderDao {
public void save(){
System.out.println("order dao save");
}
}
OrderDaoFactory
package com.itheima.factory;
import com.itheima.order.OrderDao;
import com.itheima.order.impl.OrderDaoImpl;
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
return new OrderDaoImpl();
}
}
配置类修改
class只是获取到了工厂的对象,而用factory-method才能具体到获取工厂所构建的指定方法
bean实例化(实例工厂实例化bean.了解)↓
Factory中的方法变为非静态
package com.itheima.factory;
import com.itheima.order.OrderDao;
import com.itheima.order.impl.OrderDaoImpl;
public class OrderDaoFactory {
public OrderDao getOrderDao(){
return new OrderDaoImpl();
}
}
之前静态方法中的 public static OrderDao getOrderDao(){} 改为
public OrderDao getOrderDao(){}
所以在主方法中,需要实例化一个OrderDaoFactory,从OrderDaoFactory再获取orderDao对象
public class App {
public static void main(String[] args) {
OrderDaoFactory orderDaoFactory=new OrderDaoFactory();
OrderDao orderDao=orderDaoFactory.getOrderDao();
orderDao.save();
}
}
此时运行结果
order dao save
配置类
先把工厂的bean造出来,然后创建一个新的bean,factory-bean设置所属工厂,factory-method设置工厂的指定方法
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao= (OrderDao) applicationContext.getBean("orderDao");
orderDao.save();
}
}
运行结果
order dao save
bean实例化(Factorybean.实用掌握)↓
创建一个UserDaoFactoryBean替代原本的OrderDaoFactory
package com.itheima.factory;
import com.itheima.order.OrderDao;
import com.itheima.order.impl.OrderDaoImpl;
import org.springframework.beans.factory.FactoryBean;
public class UserDaoFactoryBean implements FactoryBean
//代替原始实例工厂中创建对象的方法
public OrderDao getObject() throws Exception {
return new OrderDaoImpl();
}
public Class<?> getObjectType() {
return OrderDao.class;
}
}
applicationContext.xml
运行结果:
order dao save
此时如果想要设置非单例,需要在实现FactoryBean接口的方法(在这个例子中是UserDaoFactoryBean实现的)中加上Singleton();return为false
bean生命周期(手动配置控制)
在UserDaoFactoryBean加入两个方法init和destory
package com.itheima.factory;
import com.itheima.order.OrderDao;
import com.itheima.order.impl.OrderDaoImpl;
import org.springframework.beans.factory.FactoryBean;
public class UserDaoFactoryBean implements FactoryBean
//代替原始实例工厂中创建对象的方法
public OrderDao getObject() throws Exception {
return new OrderDaoImpl();
}
public Class<?> getObjectType() {
return OrderDao.class;
}
void init(){
System.out.println("init");
}
void destory(){
System.out.println("destory");
}
}
配置类中bean标签中加入init-method和destroy-method属性
因为配置类中的bean标签的class是指向UserDaoFactoryBean,所以在UserDaoFactoryBean添加init和destory两个方法体
运行结果:
init
order dao save
这时候发现destory方法没有运行,为什么呢?
我们写的程序是运行在java虚拟机中的,程序执行完了之后,虚拟机就强行退出了而没有销毁bean,所以的destory还得不到执行。
在主方法中,将ApplicationContext改成ClassPathXmlApplicationContext
package com.itheima;
import com.itheima.order.OrderDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao= (OrderDao) applicationContext.getBean("orderDao");
orderDao.save();
applicationContext.close();
}
}
运行结果:
init
order dao save
destory
ClassPathXmlApplicationContext是ApplicationContext的子类,其中才有close的实现方法,不过这是一种暴力关闭的方法。
方法2:
package com.itheima;
import com.itheima.order.OrderDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
applicationContext.registerShutdownHook();
OrderDao orderDao= (OrderDao) applicationContext.getBean("orderDao");
orderDao.save();
}
}
applicationContext.registerShutdownHook()是在虚拟机关闭之前,再把bean给销毁,达到同样的作用。
除了手动配置,还有实现接口控制bean生命周期。
依赖注入↓
思考:向一个类中传递数据的方式有几种?
- 普通set方法
- 构造方法
依赖注入描述了在容器中建立bean和bean之间依赖关系的过程,如果bean运行需要的是数字或者字符串呢?
- 引用类型
- 简单类型(基本数据类型与String
依赖注入的方式
-
setter注入
简单类型
引用类型 -
构造器注入
简单类型
引用类型
setter注入.引用类型↓
OrderDaoImpl
package com.itheima.order.impl;
import com.itheima.order.OrderDao;
public class OrderDaoImpl implements OrderDao {
public void save(){
System.out.println("order dao save!!!!!!!!!");
}
}
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("book dao save..........");
}
}
BookServiceImpl
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.order.OrderDao;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private OrderDao orderDao;
private BookDao bookDao;
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save(){
System.out.println("book service save ...");
bookDao.save();
orderDao.save();
}
}
配置类
setter注入.简单类型↓
在上述的代码中,修改BookDaoImpl,添加ab两个变量,并且提供setter方法
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
private int a;
private String b;
public void setA(int a) {
this.a = a;
}
public void setB(String b) {
this.b = b;
}
public void save() {
System.out.println("book dao save.........."+a+b);
}
}
修改配置文件,使用bean标签的子标签property,用name获取变量名,用value设置值
运行结果:
book service save ...
book dao save..........1000万恶之源!
order dao save!!!!!!!!!
构造器注入.引用类型↓
在上述的基础上修改BookServiceImpl,不难发现其中的setter方法变成了通过构造方法,去引用类对象
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.dao.impl.BookDaoImpl;
import com.itheima.order.OrderDao;
import com.itheima.order.impl.OrderDaoImpl;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private OrderDao orderDao;
public BookServiceImpl(BookDaoImpl bookDao1, OrderDaoImpl orderDao1) {
this.orderDao=orderDao1;
this.bookDao=bookDao1;
}
public void save(){
System.out.println("book service save ...");
orderDao.save();
bookDao.save();
}
}
修改配置文件,在id为bookService的bean中用constructor-arg标签,通过name引用BookServiceImpl中的形参(bookDao1和orderDao1),ref引用代码上部分的两个bean,让他们形成依赖。
运行结果:
book service save ...
order dao save!!!!!!!!!
book dao save..........1000万恶之源!
构造器注入.简单类型↓
在上述基础上修改BookDaoImpl,将获取变量的setter方法换成有ab两个参数的构造方法
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
private int a;
private String b;
public BookDaoImpl(int a, String b) {
this.a = a;
this.b = b;
}
public void save() {
System.out.println("book dao save.........."+a+b);
}
}
修改配置类,将id为bookDao的bean下的property标签换成constructor-arg标签,用name和value结合传参数
运行结果:
book service save ...
order dao save!!!!!!!!!
book dao save..........20000十恶不赦
上述的构造器配置中的constructor的name属性必须和类中形参一致,形参要是改名配置也要改名,这样耦合度太高,解决方法
-
使用type,让其根据类型去找
-
使用index,根据索引去找,不过要注意顺序
依赖自动装配↓
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean的过程称为自动装配。
-
自动装配用于引用类型,不能用于简单类型
-
自动装配优先级低于setter注入和构造器注入,同时出现时自动装配失效
-src
--main
---java
----com
-----itheima
------App.java
------dao
-------BookDao.java
-------impl
--------BookDaoImpl.java
------service
-------BookService.java
-------impl
--------BookServiceImpl.java
---resources
----applicationContext.xml
(接口类省略)
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save..........");
}
}
BookServiceImpl
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
applicationContext.xml
在实现类中提供setter方法,然后去配置类里面的bean里面加上autowire="byType"属性,这里是根据类型自动装配,要唯一,type名就是bean中的class名。
集合注入↓##
在BookDaoImpl做出以下修改(它的接口类省略)
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class BookDaoImpl implements BookDao {
private int[] array;
private List
private Set
private Map<String, String> map;
private Properties properties;
public void setArray(int[] array) {
this.array = array;
}
public void setList(List
this.list = list;
}
public void setSet(Set
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void save() {
System.out.println("book dao save..........");
System.out.println("array:"+array);
System.out.println("list:"+list);
System.out.println("set:"+set);
System.out.println("map:"+map);
System.out.println("properties:"+properties);
}
}
配置类
运行结果:
book dao save..........
array:[I@1f28c152
list:[suyang, xingxing]
set:[10000, 30000, 50000, 40000]
map:{1=灭霸, 2=幻视, 3=女巫}
properties:
数据源对象管理 ↓##
先在pom.xml添加坐标
Druid
c3p0
加载properties文件
上述的加载方式不够灵活,所以需要另外加一个jdbc的信息配置类jdbc.properties
jdbc.driver="com.jdbc.mysql.Driver"
jdbc.url="jdbc:mysql://localhost:3306/day17"
jdbc.username=root
jdbc.password=123456
在配置类中开启context命名空间,启用占位符
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
通过id为getname的方法就可以验证是否配置成功
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) applicationContext.getBean("getname");
bookDao.save();
}
}
运行结果:
jdbc.name:root
如果jdbc.properties配置中的jdbc.username=root改为username=root,会发生什么???
把所有jdbc.username替换成username后
运行结果:
jdbc.name:Administrator
这是因为系统环境变量中,系统名的优先级最高,所以username首先是系统的用户名。
如果一定要使username为自己所用怎么办呢?
A:在配置文件的context标签中添加一个system-properties-mode="NEVER"属性
<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"></context:property-placeholder>
加载当前工程下的多个.properties文件添加属性:location="classpath:*.properties"
<context:property-placeholder location="classpath:.properties" system-properties-mode="NEVER"></context:property-placeholder>
加载包括引用jar包等所有的.properties文件添加属性:location="classpath😗.properties"
<context:property-placeholder location="classpath:.properties" system-properties-mode="NEVER"></context:property-placeholder>
注解开发↓
如果都是用@Component注解会混乱,所以衍生了
@Controller:用于表现层的bean
@Service:用于业务层的bean
@Repository:用于数据层的bean
使用@Component定义bean
配置类
<context:component-scan base-package="com.itheima"></context:component-scan>
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import org.springframework.stereotype.Component;
@Component("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("bookDao....");
}
}
主方法
package com.itheima;
import com.itheima.dao.BookDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
}
}
纯注解开发
Spring3.0开启了纯注解开发模式,用java类来代替了配置文件
BookDaoImpl加入@Repository("bookDao")注解
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
@Repository("bookDao")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("bookDao....");
}
}
在config包下面创建一个SpringConfig类,@Configuration注明这是配置类,@ComponentScan负责扫描的范围
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
@Configuration代替了
<context:component-scan base-package="com.itheima"></context:component-scan>
@ComponentScan("com.itheima")代替其中的
<context:component-scan base-package="com.itheima"></context:component-scan>
主方法通过AnnotationConfigApplicationContext来加载配置类SpringConfig
package com.itheima;
import com.itheima.config.SpringConfig;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao= (BookDao) applicationContext.getBean("bookDao");
bookDao.save();
}
}
bean的作用范围用@Scope注解
## 注解开发依赖注入 ↓##
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
@Repository("bookDao")
@Scope("prototype")
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("bookDao....");
}
}
SpringConfig
Fpro
package com.itheima.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {
}
BookServiceImpl,使用@Autowired注解之后就不需要setter方法了,@Autowired注解默认按照类型装配
package com.itheima.service.impl;
import com.itheima.dao.BookDao;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
简单类型注入
@Value("${}")
private int a;\
获取${}需要去配置类中加上@PropertySource()数据源注解,注明数据来源,文件名不支持*.xxx的格式。
管理第三方bean ↓##
创建一个新的类,在类中创建一个方法,在该方法上加@Bean,意在让其返回值成为一个Bean。
@import可以在配置类中导入别的配置类
AOP入门案例

pom.xml
第一步创建接口
BookDao
package com.itheima.dao;
public interface BookDao {
public void save();
public void update();
}
第二步:接口实现类
BookDaoImpl
package com.itheima.dao.impl;
import com.itheima.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println(System.currentTimeMillis());
System.out.println("BookDao Save...");
}
public void update() {
System.out.println("BookDao Update...");
}
}
第三步
MyAdvice
package com.itheima.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
//定义共性功能
@Before("pt()")
public void method(){
System.out.println(System.currentTimeMillis());
}
}
第四步,配置类加上@EnableAspectJAutoProxy
SpringConfig
package com.itheima.config;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy
//@PropertySource("classpath:jdbc.properties")
//@Import(JdbcConfig.class)
public class SpringConfig {
}
第五步
主方法App运行
import com.itheima.config.SpringConfig;
import com.itheima.dao.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao=applicationContext.getBean(BookDao.class);
bookDao.update();
}
}
运行结果
1653441242924
BookDao Update...
AOP工作流程 ↓##
SpringAOP本质:代理模式
-
Spring容器启动
-
读取所有切面配置中的切入点
-
初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
. 匹配失败,创建对象
. 匹配成功,创建原始对象(目标对象)的代理对象 -
获取bean执行方法
. 获取bean,调用方法并执行,完成操作
. 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法完成最终工作的
代理(Proxy):目标对象无法直接完成工作,需要对其进行回填,通过原始对象的代理对象实现
AOP切入点表达式 ↓##
切入点:需要增强的方法
切入点表达式:要进行增强的方法的描述方式

AOP通知类型
- 前置通知
- 后置通知
- 环绕通知@Around
在MyAdvice中添加@Around,然后添加ProceedingJoinPoint形参
package com.itheima.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
//定义共性功能
@Around("pt()")
public void method(ProceedingJoinPoint proceedingJoinPointn) throws Throwable {
System.out.println("before");
proceedingJoinPointn.proceed();
System.out.println("after");
}
}
运行结果
before
BookDao Update...
after

4.返回后通知 @AfterReturning
5.抛出异常后通知 @AfterThrowing
AOP通知获取数据##
获取切入点方法的参数
JoinPoint:适用于前置、后置、返回后、抛出异常后通知
ProceedJoinPoint:适用于环绕通知
AOP总结

Spring事务
银行转账事务
SpringMVC
@EnableWebMvc是使用Java 注解快捷配置Spring Webmvc的一个注解。在使用该注解后配置一个继承于WebMvcConfigurerAdapter的配置类即可配置好Spring Webmvc。
通过查看@EnableWebMvc的源码,可以发现该注解就是为了引入一个DelegatingWebMvcConfiguration Java 配置类。并翻看DelegatingWebMvcConfiguration的源码会发现该类似继承于WebMvcConfigurationSupport的类。
其实不使用@EnableWebMvc注解也是可以实现配置Webmvc,只需要将配置类继承于WebMvcConfigurationSupport类即可
## RESTful开发风格 ##
目的是为了隐藏路径中的具体操作,提高安全性,让访问者无法通过路径去辨别你的具体操作
@RequestMapping(value="/user",method=RequestMethod.POST)
@ResponseBody
[方法1]
@RequestMapping(value="/user1",method=RequestMethod.GET)
@ResponseBody
[方法2]

就是利用请求的方法不同,进行的操作也不一样
比如说,localhost:8080/user用POST请求设置为新增用户界面,而用GET请求访问localhost:8080/user则是查询用户。

但是这些只是约定俗成的写法,并不是指定的规范。
若果请求的方法需要一个参数(该参数是从路径中获取),则需要在方法中加上注解@PathVariable,以及在Mapping中加上 {参数名}


@RequestBody、@RequestParam、@PathVariable区别和应用

## 在Controller中,注解上的改进 ## 把@RequestMapping中的value去掉(但是需要参数的要留下来,比如说原来的“/user/{id}”,要把“/ {id}”留下来),一次性加入类头,这样就不用在该类中每个方法都要加上value

类头注解中,@Controller和@RespondBody整合成@RequestController

@RequestMapping中的method.post改为@PostMapping


改进完成后

如果在mvc的默认配置中拦截所有的请求

本应给服务器(比如Tomcat)处理的css和js文件,服务器获取不到

所以应该新增一个配置类,继承WebMvcConfigurationSupport,下图中方法体的含义是:如果有“/pages/**”请求,就访问“/pages/”下的东西(记得被主配置类中扫描到,比如说在该类中添加@Configuration,将该类做成配置类,然后在著配置类中的@ComponentScan添加扫描该类)

# SSM整合 #

配置类思想

SpringConfig

JdbcConfig

MybatisConfig

## ServletConfig(Web容器配置类) ##

其中如果需要过滤器,请参考上面的1507行
SpringMvcConfig

# 项目异常处理 #






前后台协议联调

拦截器
拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
作用:
- 在指定方法前后执行预先设置好的代码
- 阻止原始方法的执行
拦截器和过滤器的区别 ##:
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
拦截内容不同:Filter对所有的内容进行增强,Interceptor仅仅针对SpringMVC的访问进行增强





拦截器可以有拦截器链,就是配置多个拦截器。
浙公网安备 33010602011771号