1.轻量级框架
体积很小,引入的jar包很少,开源代码,是一个框架。
Spring开发中的核心部分:
IOC和AOP
IOC:控制反转,将创建对象过程交给spring来进行控制
AOP:面向切面,在不修改源代码情况下,增加功能。
Spring:方便解耦,简化开发
方便测试,方便集成框架,方便对事物进行管理
Spring中用到的核心jar包
创建spring的配置文件
Spring中配置文件是xml格式
<!--配置User对象创建-->
<bean id="user" class="com.atguigu.spring5.User"> </bean>
可以用来创建对象,将java包下面的对象的包的具体位置放在class中去,然后起一个名字放在id里面。
xml格式文件最好起一个名字叫
beans.xml作为spring的配置文件
bean中一个bean就是一个对象
<?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">
<!--id是对象名字,class是对象的类-->
<bean id="hello" class="com.kuang.pojo.Hello">
</bean>
</beans>
<?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">
<!--id是对象名字,class是对象的类-->
<bean id="hello" class="com.kuang.pojo.Hello">
<!--设置值-->
<property name="str" value="死神"></property>
</bean>
</beans>
彻底不用去,配置一些东西了,修改只需要在底层修改beans操作。
玩配置文件就可以了
6.测试代码
public class TestSpring5 {
@Test
public void testadd(){
//1.加载配置文件
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean1.xml");//将配置文件加载进内存
User user = classPathXmlApplicationContext.getBean("user", User.class);//获得加载进来的类创建对象
//这个user就是创建对象时候那个id的值
}
}
IOC的本质:
通过无参构造创造对象,默认方式!
但是你想用有参构造也可以,
IOC是什么:控制反转,
将对象创建和对象调用的过程交给spring去进行管理
IOC为了降低耦合过程。
IOC底层原理:
1.xml解析
2.工厂模式:为了降低耦合,
建立一个中间工厂,然后在工厂中得new 对象
再互相调用,然后极大程度降低耦合
**
IOC本质是一种思想
二、什么是IOC? 2.1 了解IOC思想
大概了解了IOC是控制反转,至于现在我们并不清楚它的思想和作用。那么问题来了,IOC(控制反转)是什么呢?
控制反转,简称IOC。顾名思义,它是由“控制”和“反转”两个词语组合而成。那么我们就顺藤摸瓜,分别分析一下这两个词语!
2.3 反转
反转一词,我们想的也很多。比如说,达成反转的条件必须是两个对象,有反转就有正转 ,然后就是反转了些什么 。那么我们也一一列举说明:
在Java中我们是间接的实用程序来创建对象,这可以看作正转。那有了IOC容器,一下子就变了,我们不用自己new对象,**而是直接反转为由IOC创建生成依赖对象并存入IOC容器中使用IOC容器创建对象我们只需要通过配置来告诉它需要创建的对象是什么,并标识一下以后使用什么来获取IOC容器中创建好的对象即可(配置使用IOC的过程),这时候等你想要IOC容器中对象就直接用这个唯一标识来获取就好,而获取的过程肯定是IOC通过这个唯一标识来查找并返回给我们该对象也许有的小伙伴还是不明白反转。**为什么要把IOC容器帮我们创建对象的行为叫反转呢?因为由容器帮我们查找及注入依赖对象,对象只是被动地接受依赖对象。如果不反转呢?开发者就需要创建对象,并找到、获取、使用该对象,此过程中的所有都有开发者来控制的
三、IOC的作用
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。比如:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。在使用了IOC之后呢?A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(xml)来指定既然由配置文件来指定创建对象关系,就大大降低了各个组件之间的强耦合并有利于维护,是项目变得更加稳健灵活
四、IOC解决Dao层和Service层的强耦合
在原始的Web开发中,Dao层和Service层是密不可分的。Dao层为数据访问层,只与数据库打交道。Servcie层为业务处理层,只处理实现相应的业务。而我们将Web开发中的Dao层和Service层串在一起,就需要在Service层new一个私有的Dao层实现对象(XxxDaoImpl)。有了IOC的思想,再想想传统的Dao层与Service层的实现就显得很不灵活,一旦修改了Dao层实现类,就必须将项目中的源码都修改掉,显然是一件非常可怕的事情。
五、使用IOC解决Dao层和Service层的强耦合
既然解决Dao层和Service层的强耦合那必须得这两个组件对吧。
IOC是个容器,容器将对象注入进来,降低耦合!
IOC最重要作用是降低耦合
就像借钱一样(你把钱,借给亲戚,你不好意思放高利贷,是不是,因为血缘关系让你们耦合在一起,咋办???好报=办,把钱给p2p平台!你不用去催债务,催债的事让平台去做,是不是降低了耦合!!是吧,大量降低了耦合,不用舔着脸去催债了)
传统的private dao = new dao()这种玩意,问题是,程序员主动创建对象,对象创建权在程序员手中,
而getter和setter方法好处是,创建对象权利交给了需求,我们从程序主动new 对象,变成成了,程序底层源代码被动接受对象的注入。
程序员不用管理对象的创建了,系统的耦合行大幅度下降。
说白了就是程序员将创建程序对象的权利交给别人。
**
狂神给的spring框架的导包
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
</dependencies>
这一个包可以整合所有包。
3.反射
获取class文件
IOC:XML配置文件,配置好创建的对象,
第一步,配置XML文件,配置好解析对象
第二部,创建工厂类和让服务类和dao类型进行交互。
IOC是一个容器,容器中就是一个工厂
IOC容器的两种实现方式
1.Beanfactory(一个接口):IOC内部使用接口,不给开发人员使用
在加载配置文件的时候不会创建对象,只有使用的时候才会创建对象。
2.ApplicationContext(),是Beanfactory的子接口,面向开发使用。
加载配置文件的时候,就会创建对象
ApplicantionContext()接口有一些实现类,
一个是系统全盘的路径,另外一个是,只是写在配置文件中的名字。
Spring的Bean管理:
1.用spring创建对象
2.用spring注入属性
Spring管理操作的两种方式:
1.用xml配置文件方式进行操作
(1)创建对象
刚才演示过了,
在bean标签中直接添加属性就行了。
id:相当于身份证号码
class:相当于类的全路径
创建对象时候默认是无参构造
xml中的一些属性
1.Spring配置
@Test
public void TestHello(){
ApplicationContext Context = new ClassPathXmlApplicationContext("bean1.xml");
//这一步是获取spring容器
Hell hell = Context.getBean(Hell.class);//这么取出来也可以
Hell hell1 =(Hell) Context.getBean("hell");//这么取出来可以
//直接按照bean里面的id去取出也可以
//直接获取对象
System.out.println(hell);
1.起别名
<?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">
<!--id是对象名字,class是对象的类-->
<bean id="hell" class="com.kuang.pojo.Hell">
<!--设置值-->
<property name="str" value="dfsa"/>
</bean>
<!--给一个对象,或者一个类起别名-->
<alias name="hell" alias="he"></alias>
</beans>
直接这样起别名也行,还可以起多个别名
2.import
这样可以导入进来。
在开发环节,整个项目总的bean都在applicatinoContext里面,但是别的团队成员会设计很多bean,想把这些bean合并到一起,就需要
Import
(2)DI:依赖注入,给对象注入属性
1.setter方法注入属性
注入属性。
<!--配置User对象创建-->
<bean id="book" class="com.atguigu.spring5.Book">
<!--完成属性的注入-->
<property name="people" value="3"> </property>
</bean>
2.有参构造方式注入属性
<bean id="book" class="com.atguigu.spring5.Book">
<constructor-arg name = "people" value = "5" ></constructor-arg>
</bean>
向标签中注入空值
注射进去,特殊值
注入外部bean
比图service层调用dao层的方法
package com.atguigu.service;
import com.atguigu.dao.UseDao;
public class Userservice {
private UseDao userDao;//先创建dao层属性,要引用别人的对象,先创建别人
//通过set方法完成注入
public void setUserDao(UseDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service");
userDao.update();
}
}
public class UserDaoImpl implements UseDao {
@Override
public void update() {
System.out.println("我输出了 ");
}
}
<!--创建service和dao对象进行创建-->
<bean id="userservice" class="com.atguigu.service.Userservice">
<property name="userDao" ref="userDao">
<!--这里要注入得是对象,引用外部对象-->
</property>
</bean>
<!--接口要new实现类-->
<bean id="userDao" class="com.atguigu.dao.UserDaoImpl"> </bean>
看起来应该是所有数据类型注入都在这里了。
是不是,可以一次性读很多xml进来,这一步其实就是获取容器。
<property name="books">
<array>
<value>红楼梦</value>
<value>水浒</value>
</array>
</property>
map的注入方式
注入属性,内部bean和级联赋值
1对多关系,
内部bean,往属性中加值,
public class dept {
private String dname;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
package com.atguigu.bean;
public class Emp {
private String ename;
private String gender;
private dept dept;
public String getEname() {
return ename;
}
public String getGender() {
return gender;
}
public com.atguigu.bean.dept getDept() {
return dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(com.atguigu.bean.dept dept) {
this.dept = dept;
}
}
bean的注解配置
在属性的内部,嵌套上一个bean对象
<?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-->
<bean id="emp" class="com.atguigu.bean.Emp">
<property name="dept">
<bean id="dept" class="com.atguigu.bean.dept">
<property name="dname" value="安保部门">
</property>
</bean>
</property>
</bean>
</beans>
级联赋值
1.通过xml方式,注入集合这个属性。
- 数组
- map
- set
public class dept {
private String dname;
private String[] course;
private List<String> list;
private Map<String,String> map;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
完成配置文件
注进入一个数组
<?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-->
<bean id="dept" class="com.atguigu.bean.dept">
<property name="course">
<array>
<value>课程</value>
<value>化学</value>
</array>
</property>
<property name="list">
<list>
<value>英文</value>
<value>中文</value>
</list>
</property>
<property name="map">
<map>
<entry key="死神" value="我"> </entry>
<entry key="死神" value="我"> </entry>
</map>
</property>
</bean>
</beans>
在集合注入中设置一个对象类型的值。
一个包含大量对象的list
ref就是跟对象有关系。
<property name="courseList">
<list>
<ref bean="course2"></ref>
<ref bean="course1"></ref>
<ref bean="course3"></ref>
<ref bean="course4"></ref>
</list>
</property>
</bean>
<bean id="course1" class="com.atguigu.bean.Course">
<property name="cname" value="政治">
</property>
</bean>
<!--创建很多course类对象-->
<bean id="course2" class="com.atguigu.bean.Course">
<property name="cname" value="英语">
</property>
</bean>
<bean id="course3" class="com.atguigu.bean.Course">
<property name="cname" value="化学">
</property>
</bean>
<bean id="course4" class="com.atguigu.bean.Course">
<property name="cname" value="生物">
</property>
</bean>
把集合注入部分提取出来
Spring配置文件中引入
util空间
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--相当于直接创建一个人List集合-->
<util:list id="book">
<value>数据</value>
<value>数据</value>
<value>数据</value>
</util:list>
<bean id="dept" class="com.atguigu.bean.dept">
<property name="list" ref="book">
</property>
</bean>
</beans>
相当于创建了一个公共空间,建立了一个List对象,然后给这个List对象创建了东西
最后将这个List对象放进一个list里面去。
Spring中有两种bean,一种普通bean,另外一种factoryBean工厂
普通bean你在xml里定义的类,就会返回这个类的对象
工厂bean返回类型和定义类型不一定相同。
1.让类实现factoryBean接口
重写其中getIbject方法,可以决定返回的类类型
定义类型和返回类型可以不一样
bean的作用域
1.可以在spring中设置好,我创建的bean是单实例,还是多实例。通过bean中的scope属性,可以设置是单实例还是多实例
single单实例
prototype表示多实例
你要的太多我就晚一点创建实例
Bean的生命周期
(2)初始化方法,在类java中去写一个方法,然后通过
bean中的init-method方法去指定这个放噶是bean的初始化方法。
(3)销毁方法,指定类中一个方法作为类销毁时候执行的方法
<bean id="dept" class="com.atguigu.bean.dept" init-method="getCourse" destroy-method="getMap">
<property name="list" ref="book">
</property>
</bean>
不用的类需要手动去进行销毁、
public class TestSpring5 {
@Test
public void testadd(){
//1.加载配置文件
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean1.xml");//将配置文件加载进内存
dept dept = classPathXmlApplicationContext.getBean("dept", dept.class);
for(String c:dept.getList()){
System.out.println(c);
}
classPathXmlApplicationContext.close();//可以直接将bean销毁,销毁之后,销毁方法也会启动
}
}
自动装配:
1.不需要手动注入属性,自动将匹配名称类型将数据装进去。
autowrite属性两个值:
1.byName,根据类的名称,完成注入
要求bean的id值和属性名称要一样。
说白了就是需要注入的bean的id和类中属性的名字必须相当。
package com.atguigu.bean;
public class Emp {
private String ename;
private String gender;
private dept dept;
public String getEname() {
return ename;
}
public String getGender() {
return gender;
}
public com.atguigu.bean.dept getDept() {
return dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(com.atguigu.bean.dept dept) {
this.dept = dept;
}
}
package com.atguigu.bean;
import java.util.List;
import java.util.Map;
public class dept {
private String dname;
private String[] course;
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
private List<String> list;
private Map<String,String> map;
private List<Course> courseList;
public String[] getCourse() {
return course;
}
public void setCourse(String[] course) {
this.course = course;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="dept" class="com.atguigu.bean.dept" autowire="byName">
</bean>
<!--byname就是,根据名字将类自动注入进入-->
<bean id="emp" class="com.atguigu.bean.Emp"> </bean>
</beans>
说白了,就是不需要你自己去注入类了,他会根据类的名字自己将成员里面的类注入进去的。
2.byType,根据类型注入
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="dept" class="com.atguigu.bean.dept" autowire="byType">
</bean>
<!--byname就是,根据名字将类自动注入进入-->
<bean id="emp" class="com.atguigu.bean.Emp"> </bean>
</beans>
根据类型注入,很容易出现问题,就是类发生冲突。
外部属性文件,比如JDBC的配置文件导入:
数据库连接池
1.首先将外部context引入;
上面这里修证一下
<?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:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
第二建立一个property空间
开发中推荐
2.用注解方式实现
进行bean管理
注解配置
注解功能是一样的
基于·注解方式实现创建,
1.
component用于模型,数据模型
service用于进入dao层
repository用于访问数据库
controller用于控制页面跳转,转发数据。
扫描所有注解
2.开始组件扫描
一些细节配置:
1.base-package不配置,扫描所有类
两个例子:
<context:component-scan base-package="com.atguigu.springmvc" use-default-filters="false">
<!--这个配置开启,不再默认扫描所有,而是有选择性筛选扫描-->
<context:include-filter type="annotation"
<!--根据注解进行扫描-->
expression="org.springframework.stereotype.Controller"/>
<!--有controller的注解进行扫描-->
</context:component-scan>
<context:component-scan base-package="com.atguigu.springmvc">
<!--exclude是不包含的意思,说明不包含Controller的都可以扫描进来-->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<?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.atguigu.bean,com.atguigu.dao,com.atguigu.bean"> </context:component-scan>
<!--开启注解配置-->
<context:annotation-config></context:annotation-config>
</beans>
注解配置一下
注解方式,属性注入:
1.Autowired 根据属性类型自动装配
注解方式实现属性注入
第一步创建对象(添加注解可以创建对象)
第二在属性上面加注解
AutoWired根据对象名字进行注入
这样有个问题,当我一个类创建多个对象时候,我怎么直到注入哪个对象?
//id值等于value,相当于进行了注解配置
//里面value值可以不写,默认值是类字母小写
@Service(value = "userService")
public class Userservice {
@Autowired//根据类型完成注入,自己找注入类型
private UseDao userDao;//先创建dao层属性,要引用别人的对象,先创建别人
//通过set方法完成注入
public void setUserDao(UseDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add.....");
userDao.update();
}
}
2.Qualifier 根据属性名称完场注入
和autowired一起使用
qualifiier中,要写上注入对象的名字
这样比较安全,即使一个类有多个对象也没问题
类型加对象名
就相当于,让你去接一个人,告诉你这个人红衣服,蓝帽子,黑外套,你依然可能接错,但是如果还告诉你这个人名字,你就接不错了。
AUtuowired主要是完成属性注入的一个注解。
3.Resource根据属性名称加类型完成注入
根据名称和类型都可以完成注入
上面都是注入对象
Resource是集大成者,先根据对象名字去找,然后根据对象类型去找。
4.Value根据普通类型注入
//id值等于value,相当于进行了注解配置
//里面value值可以不写,默认值是类字母小写
@Service(value = "userService")
public class Userservice {
@Autowired//根据类型完成注入,自己找注入类型
private UseDao userDao;//先创建dao层属性,要引用别人的对象,先创建别人
@Value(value = "1")
private int s;
//通过set方法完成注入
public void setUserDao(UseDao userDao) {
this.userDao = userDao;
}
public void add(){
System.out.println("service add.....");
System.out.println(s);
}
}
普通属性注入方式
纯注解开发,完全不需要配置文件
将配置文件中内容交给配置类
首先建立配置类
注解开发使用这个读取配置文件
这里就相当于床架你一个
beans这就是一个bean
package com.atguigu.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
//用配置文件进行配置,扫描包
@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
public class TestSpring5 {
@Test
public void testadd() {
//1.加载配置文件
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Userservice userService = context.getBean("userService", Userservice.class);
userService.add();
}
}
``
狂神的spring小课堂:
spring中放这几个就行了。
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
配置文件这么放
xml配置文件。
使用注解开发:
第一步在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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
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
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--注解支持-->
<context:annotation-config/>
</beans>
别忘记加一个包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>