Spring

本文深入介绍了Spring框架的核心特性,包括控制反转(IOC)的概念和实现,如无参构造、有参构造的bean创建,以及对象的属性注入。此外,还讲解了AOP(面向切面编程)的基本原理,如动态代理、切点表达式和通知类型。最后,讨论了Spring中的注解配置,包括@Autowire、@ComponentScan等,以及完全注解开发的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录


2021.07.07

Spring

优点

  • Spring是一 个开源的免费的框架(容器)

  • Spring是一 个轻量级的、非入侵式的框架!

  • 控制反转(I0C),面向切面编程(AOP)

    ​ IOC: 控制反转,把创建对象过程交给Spring进行管理。

    ​ Aop: 面向切面,不修改源代码进行功能增强。

  • 支持事务的处理,对框架整合的支持

IOC

变量名

的对象

相当于给对象中的属性设置一个值(属性的注入)

name 属性名 建议养成一个习惯 小写类名

ref 引用Spring容器中创建好的对象

value 具体的值,基本数据类型

<bean id="hello" class="com.Huiex.pojo.Hello">
    <property name="str" value="Spring"/>------把str属性附了值为“Spring” 用set方法进行注入
</bean>

这个过程就叫控制反转:

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.

反转:程序本身不创建对象,而变成被动的接收对象

依赖注入:就是利用set方法来进行注入的.

IOC是-种编程思想 ,由主动的编程变成被动的接收 .

所谓的IOC,一句话搞定:对象由Spring来 创建,管理,装配

IOC创建对象的方式

使用无参构造

默认使用无参构造

//@AllArgsConstructor
public class User {
    //Lombok 永远滴神
    @Getter
    @Setter
    private String name;

    public void show(){
        System.out.println("name" + name);
    }
}

在deans.xml文件中

<bean id="User" class="com.Huiex.pojo.User">
    <property name="name" value="胖子君"/>
</bean>

使用有参构造

@AllArgsConstructor----------------------------------------------------------有参构造
public class User {
    //Lombok 永远滴神
    @Getter
    @Setter
    private String name;

    public void show(){
        System.out.println("name" + name);
    }
}
1.下标赋值
<bean id="User" class="com.Huiex.pojo.User">
    <constructor-arg index="0" value="下标赋值"/>
</bean>
2.参数名
<bean id="User" class="com.Huiex.pojo.User">
    <constructor-arg name="name" value="参数名赋值"/>
</bean>

IOC使用对象

通过context.getBean方法,创造出User对象(实际上是在IOC容器中取出对象)

@Test
public void Test(){
    //得到IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

    //从IOC容器中取出
    User user = (User) context.getBean("User");//强转一下
    
    user.show();
}

在配置文件加载的时候,容器中管理的对象就已经初始化了

Spring配置文件

applicationContext.xm

官方文档中的Spring配置文件(beans.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"
    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>

alias别名

没什么好说的

就是将bean的id起一个别名

    <bean id="User" class="com.Huiex.pojo.User">
        <constructor-arg name="name" value="参数名赋值"/>
    </bean>

    <alias name="User" alias="userNew"/>--------------------------------------起一个别名
@Test
public void Test(){
    //得到IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

    User user = (User) context.getBean("userNew");-----------------------------使用别名
    user.show();
}

Bean的配置

id : bean的唯一 标识符,相当于对象名
class : bean 对象所对应的全限定名:包名+类型
name :也是别名,而且name可以同时取多个别名(三个名字 User, user1 ,user2)

	<bean id="User" class="com.Huiex.pojo.User" name="user1,user2">
   	 	<constructor-arg name="name" value="bean标签"/>
	</bean>

import

这个import, 一般用于团队开发使用,他可以将多个配置文件,导入合并为一个
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利
用import将所有人的beans.xml合并为一个总的!

资源目录下有多个bean配置文件,applicationContext.xml为主

resources目录下
	applicationContext.xml
	beans.xml
	bean2.xml
	bean3.xml

在applicationContext.xml中用import标签导入其他配置文件

<?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">

    <import resource="beans.xml"/>
    <import resource="bean2.xml"/>
    <import resource="beans.xml"/>
    
</beans>

仍然可以通过主配置文件applicationContext.xml创建其他beans.xml文件的对象

@Test
public void Test(){
    //得到IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    User user = (User) context.getBean("user2");//强转一下
    user.show();
}

属性注入XML

构造器注入

使用无参构造

默认使用无参构造

//@AllArgsConstructor
public class User {
    //Lombok 永远滴神
    @Getter
    @Setter
    private String name;

    public void show(){
        System.out.println("name" + name);
    }
}

在deans.xml文件中

<bean id="User" class="com.Huiex.pojo.User">
    <property name="name" value="胖子君"/>
</bean>

使用有参构造

@AllArgsConstructor----------------------------------------------------------有参构造
public class User {
    //Lombok 永远滴神
    @Getter
    @Setter
    private String name;

    public void show(){
        System.out.println("name" + name);
    }
}
1.下标赋值
<bean id="User" class="com.Huiex.pojo.User">
    <constructor-arg index="0" value="下标赋值"/>
</bean>
2.参数名
<bean id="User" class="com.Huiex.pojo.User">
    <constructor-arg name="name" value="参数名赋值"/>
</bean>

依赖(set)注入

使用Set方法注入

就是JavaBean中的set方法

@Data//yyds
public class Address {

    private String name;-----------------------------------------空值
    private User user;-------------------------------------------引用类(对象)
    private String[] books;--------------------------------------数组
    private List<String> hobbys ;--------------------------------List
    private Map<String,String> card;-----------------------------Map
    private Set<String> games;-----------------------------------集合
    private String wife;-----------------------------------------字符串(nullprivate Properties info;-------------------------------------一个特殊的类型(不重要)
    
}

头文件

<?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">

    <import resource="beans.xml"/>
	<!--    Bean注入,也就是属性是对象,从bean中(IOC容器)里面的对象-->
    <bean id="Address" class="com.Huiex.pojo.Address">

引用类

Bean注入,也就是属性是对象

ref属性 从bean中(IOC容器)里面的对象

在这里插入图片描述

<!--        引用类(对象)-->
        <property name="user" ref="user1"/>

数组

<!--        数组-->
        <property name="books">
            <array>
                <value>易点</value>
                <value>易圈</value>
                <value>等风</value>
            </array>
        </property>

列表

<!--        list-->
        <property name="hobbys">
            <list>
                <value>0</value>
                <value>3</value>
                <value>7</value>
            </list>
        </property>

Map

<!--        Map-->
        <property name="card">
            <map>
                <entry key="H" value=""/>
                <entry key="e" value=""/>
            </map>
        </property>

集合

<!--        set-->
        <property name="games">
            <set>
                <value>z</value>
                <value>J</value>
                <value>L</value>
            </set>
        </property>

null

<!--        null-->
        <property name="wife">
            <null/>
        </property>

空值

<!--        空值-->
        <property name="name" value=""/>

property

​ 这个类型和map差不多只不过只有key,valuex写在标签外面

<!--        property-->
        <property name="info">
            <props>
                <prop key="username">root</prop>
                <prop key="password">183303</prop>
            </props>
        </property>
    </bean>
</beans>

扩展方法注入

P命名空间注入

xmlns:p="http://www.springframework.org/schema/p"   从官网找的

通过无参构造器注入:

<?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:p="http://www.springframework.org/schema/p"----------------------配置
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="Hello" class="com.Huiex.pojo.Hello" p:str="通过无参"/>
								        -----------------将”通过无参“赋值给`str`属性
</beans>

C命名空间注入

xmlns:c="http://www.springframework.org/schema/c"    也是从官网找的,明白我什么意思吗

通过有参构造器注入:

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="Hello" class="com.Huiex.pojo.Hello" c:str="通过有参构造"/>
</beans>

Bean的自动装配

  • 自动装配是Spring满足bean依赖一种方式

  • Spring会在上下文中自动寻找,并自动给bean装配属性

  • 在Spring中有三种装配的方式

    ​ 1.在xml中显示的配置

    ​ 2.在java中显示配置

    ​ 3.隐式的自动装配bean

常规的手动装配

@Data
public class People {
    private String name;
    private Dog dog;
    private Cat cat;
}
<bean id="dog" class="com.Huiex.pojo.Dog"/>
<bean id="cat" class="com.Huiex.pojo.Cat"/>


<bean id="People" class="com.Huiex.pojo.People">
    <property name="name" value="胖子君"/>
    <property name="cat" ref="cat"/>---------------------------利用ref引用IOC中的dog对象
    <property name="dog" ref="dog"/>
</bean>

byname

  • byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id
  • byname的时候,需要保证所有bean的id唯一, 并且这个bean需要和自动注入的属性的set方法的值一致
    <bean id="dog" class="com.Huiex.pojo.Dog"/>---------------------------重点小写  dog
    <bean id="cat" class="com.Huiex.pojo.Cat"/>

    <bean id="People" class="com.Huiex.pojo.People" autowire="byName">
        <property name="name" value="胖子君"/>
    </bean>
  • autowire="byName"会自动在容器上下文中查找对应的bean id,即会根据setDog方法找到 dog对象 注意是小写,所以Dog的bean id要为dog(局限性太大了)

bytype

byName:会自动在容器上下文中查找,和自己对象属性的类型对应的bean id

bytype的时候,需要保证所有bean的class唯一, 并且这个bean需要和自动注入的属性的类型一致

    <bean id="dog" class="com.Huiex.pojo.Dog"/>
    <bean id="cat" class="com.Huiex.pojo.Cat"/>
    
    <bean id="People" class="com.Huiex.pojo.People" autowire="byType">
        <property name="name" value="胖子君"/>
    </bean>

Bean作用域

单例模式

spring默认模式 同一对象在IOC容器中只有一个

scope="singleton"设置 单例模式

<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

在这里插入图片描述

	<bean id="cat" class="com.Huiex.pojo.Cat" scope="singleton"/>----scope可省略
	<bean id="cat22" class="com.Huiex.pojo.Cat"/>

测试体验:

@Test
public void peopleTest(){
    ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
    
    Cat cat = context.getBean("cat", Cat.class);
    Cat cat22 = context.getBean("cat22", Cat.class);
    Cat cat33 = context.getBean("cat", Cat.class);
    
    System.out.println(cat == cat22);--------false 
    System.out.println(cat == cat33);--------true 同一个对象(出自同一个bean),只是名字不同
}

原型模式

每次从容器中get的时候,都会产生一个新对象

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

在这里插入图片描述

其他

其余的request、session. application. 这些个只能在web开发中使用到

注解实现自动装配

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"
    xmlns:context="http://www.springframework.org/schema/context"-------------这个
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context-----------------------这两个
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>------------------------------------------还有这个
    
</beans>

2.开启注解的支持

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>			---------------<!--开启注解的支持-->

    <bean id="Dog" class="com.Huiex.pojo.Dog"/>
    <bean id="Cat" class="com.Huiex.pojo.Cat"/>
    <bean id="People" class="com.Huiex.pojo.People"/>

</beans>

3.在属性上添加注解

@Autowired

(中文翻译 自动连线)

作用

​ 自动装配已经在IOC容器里面的对象

  • 直接在属性上使用即可,也可以在set方式上使用

  • Autowired注解是智能识别的

    当注入容器存在多个同一类型的对象时,就是根据byName进行装配

    当注入在IoC容器中该类型只有一个时,就通过byType进行装配

    <!--开启注解的支持-->
    <context:annotation-config/>

    <bean id="dog" class="com.Huiex.pojo.Dog"/>
    <bean id="cat" class="com.Huiex.pojo.Cat"/>
    <bean id="People" class="com.Huiex.pojo.People"/>

在@Autowired注解下,会自动去IOC容器中寻找符合属性dog的byName的bean id

如果找不到符合的bean id 则寻找byType

@Data
public class People {
    private String name;
    
    @Autowired-------------------------------------------------------在属性上添加注解
    private Dog dog;
    
    @Autowired(required = false)--------------------------------设置这个对象,允许为空
    private Cat cat;
}
属性

@Autowired(required = false)

如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空

@Qualifier

@Qualifier(value=“xx”) 配和@Autowired的使用,指定一个唯一的bean对象注入

像以下这种情况,配置文件中创建了有两个Cat类型的cat对象,并且byName都不符合bean id

	<bean id="cat33" class="com.Huiex.pojo.Cat"/>
	<bean id="cat22" class="com.Huiex.pojo.Cat"/>

但是byType又一样,所以用@Qualifier(value = “cat22”)指定bean id (真好用,这个 )

public class People {
    
    @Autowired(required = false)
    @Qualifier(value = "cat22")
    private Cat cat;

    private String name;
    @Autowired
    private Dog dog;
}

没有可用的“com.Huiex.pojo.Cat”类型的合格 bean:预期单个匹配 bean,但发现 2:cat33,cat22

半注解开发

配置文件-组件扫描

指定要主描的包,这个包下的注解就会生效

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

配置文件

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--指定要主描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.Huiex.pojo"/>
    <!--开启注解的支持-->
    <context:annotation-config/>
</beans>

自动装配bean

@Component组件,放在类上,说明这个类被Spring管理了,就是bean

表明一个类会作为组件类,并告知Spring要为这个类创建bean

@Data
@Component("user")--------------------相当于<bean id="user"class="com.Huiex.pojo.User">
public class User {
    private String name = "胖子君";
}

属性注入

@Value

@Data
@Component("user")
public class User {
    @Value("胖子君")-------------------------相当于<property name="name" value="胖子君"/>
    private String name ;
}

衍生的注解

@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层

  • dao -------------------@Repository
  • service ---------------@Service
  • controller------------@Controller

这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean。

作用域

@Scope

@Data
@Component("user")
@Scope("singleton")---------------------------------------------开启单例模式(默认)
public class User {
    @Value("胖子君")
    private String name ;
}

对比

xml与注解

  • ​ xml更加万能,适用于任何场合!维护简单方便
  • ​ 注解不是自己类使用不了,维护相对复杂

xml与注解最佳实践

  • ​ xml用来管理bean;
  • ​ 注解只负责完成属性的注入;

完全注解开发

和半注解开发就一个区别,用了Config类代替了xml文件

JavaConfig

建立一个JavaConfig配置类 代替以下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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--指定要主描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.Huiex.pojo"/>
    <!--开启注解的支持-->
    <context:annotation-config/>
</beans>

配置类

配置类代替配置文件

@Configuration  
@ComponentScan("com.Huiex.pojo")
public class Config {
    }
}

@Configuration (汉译配置)

  • ​ 会被Spring容器托管,注册到容器中,因为他本来就是一 个@Component
  • ​ 代表这是一 个配置类,就和我们之前看的beans . xml

@ComponentScan

相当于配置文件中的 <context:component-scan base-package="com.Huiex.pojo"/>

自动装配bean

@Bean

可有可无@Bean 一般用来获取数据库连接池Connection这种对象

  • ​ 注册一个bean,就相当于bean标签
  • ​ @Bean(name =“ XX”) 中XX就相当于bean的``id` 默认为这个方法的名字,
  • ​ 这个方法的返回值,就相当bean标签中的class属性

相当于<bean id="getStudent"class="com.Huiex.pojo.Student">

@Configuration  
@ComponentScan("com.Huiex.pojo")
public class Config {
    @Bean
    public Student getStudent(){
        return new Student();------------------------------就是返回要注入到bean的对象
    }
}
  • 这里自己的对象直接扫描就可以注入,@Bean一般用于外部第三方类对象注入,比如数据源

有了@bean没有@ComponenScan也行,,不过不建议,极其

属性注入

@Value

相当于<property name="name" value="胖子君"/>

@Data
@Component-----------------------------------------------自动装配bean
public class Student {
    @Value("胖子君")--------------------------------------属性注入
    private String name;
}

详细见上面的注解

创建对象

AnnotationConfigApplicationContext

如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig 上下文来获取,通过配置类的class对象加载

@Test
public void annotationTest(){
    ApplicationContext context =
            new AnnotationConfigApplicationContext(Config.class);
    Student student = context.getBean("getStudent",Student.class);
    System.out.println(student.toString());

}

配置类中的方法名就是bean id

@Configuration  
@ComponentScan("com.Huiex.pojo")
public class Config {
    @Bean
    public Student getStudent(){
        return new Student();------------------------------就是返回要注入到bean的对象
    }
}

代理模式

在这里插入图片描述

静态代理

角色分析

  • ​ 抽象角色: 一般会使用接口或者抽象类来解决
//租房
public interface Rent {
    public void rent();
}
  • ​ 真实角色: 被代理的角色
//房东
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要出租房子");
    }
}
  • ​ 代理角色: 代理真实角色,代理真实角色后,我们一般会做一-些附属操作
//中介
public class Proxy(){
    
}
  • ​ 客户: 访问代理对象的人
/**租客*/
public class Client {
    }

代理模式的好处

  • 可以使真实角色的操作更加纯粹!不用去关注一 些公共的业务
  • 公共也就就交给代理角色!实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理

代理模式的缺点

  • 一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低

AOP实现机制

在这里插入图片描述

动态代理

  • 动态代理和静态代理角色一样

  • 动态代理的代理类是动态生成的,不是我们直接写好的

  • 动态代理分为两大类:1.基于接口的动态代理,2.基于类的动态代理

    • 基于接口:JDK动态代理
    • 基于类: cglib
    • java字节码实现:javasist

JDK动态代理

作用

有接口情况,使用JDK动态代理

创建接口实现类代理对象,增强类的方法。

在这里插入图片描述

newProxyInstance方法

使用Proxy类里面的newProxyInstance方法创建代理对象

在这里插入图片描述

方法有三个参数:

l 第一参数,当前类的加载器。

l 第二参数,增强方法所在的类 实现的 接口,支持多个接口。接口为class[ ]类型

l 第三参数,一个类的对象,该类实现InvocationHandler接口,在该类中创建代理对象,写增强的方法

JDK动态代理代码

CGLIB动态代理

l 没有接口情况,使用CGLIB动态代理

创建子类的代理对象,增强类的方法。

在这里插入图片描述

InvocationHandler是由代理实例的调用处理程序实现的接口。
每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调 用将被编码并分派到其调用处理程序的invoke方法。

面向切面编程

  1. 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得

业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

  1. 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

  2. 使用登录例子说明AOP
    在这里插入图片描述

术语

连接点

类里面哪些方法可以被增强,这些方法称为连接点

在这里插入图片描述

实际被真正增强的方法,称为切入点

通知(增强)
  1. 实际增强的逻辑部分称为通知(增强)

  2. 通知有多钟类型

  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 异常通知
  5. 最终通知 finally
切面

是动作

把通知应用到切入点过程

AOP

基于AspectJ实现AOP操作

  • l 代替JDK动态代理
  • l Spring框架一般都是基于Aspect实现AOP操作
  • l AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spimg.框架依起使用,进行AOP操作。

1.导入依赖

pom.xml

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

2.开启aop注解支持

在配置文件中开启aop注解支持 <aop:aspectj-autoproxy/>

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启aop注解支持-->
    <aop:aspectj-autoproxy/>

</beans>

3.配置类

@Configuration
@ComponentScan(basePackages = {"com.Huiex"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {
    
}

@EnableAspectJAutoProxy(proxyTargetClass = true)开启拦截器,当用全注解实现AOP时,要配置

4.建立接口和要被增强的实现类

interface

public interface UserService {
    public void add();
    public void delete();
}

Impl

@Component---------------------------------------------------标注该类,生成该类的Beans对象
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个add");
}

5.切面(代理)类

@Component
@Aspect//标注这个类是一个切面
public class PointCut {
    @Before(value = "execution(* com.Huiex.service.UserServiceImpl.add(..))")
    public void before(){
        System.out.println("方法执行前");
    }
}
  • @Component标注该类,生成该类的Beans对象
  • @Aspect 标注这个类是一个切面
  • @Before(value = “execution(* com.Huiex.service.UserServiceImpl.add(…))”)设置切入的方法

6.Test2

public class MyTest {
    @Test
    public void test(){
        ApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class);
        
        UserService userService =
                context.getBean("userServiceImpl", UserServiceImpl.class);
        
        userService.add();
        userService.delete();
    }
}

结果

方法执行前
增加了一个add
删除了一个delete

切入点表达式

作用

设置对哪个类里面的哪个方法进行增强。

语法结构

execution ( [返回类型] 权限修饰符 [类全路径]. [方法名称] ( [参数列表] ) )

1.对com.atguigu.dao.BookDao类里面的add进行增强。

@Before(value = "execution(* com.Huiex.service.UserServiceImpl.add(..))")
						返回类型所有 修饰符省略 类的全类名.方法名(..)参数用两点表示

2.对com.atguigu.dao.BookDao类里面的所有的方法进行增强。

@Before(value = "execution(* com.Huiex.service.UserServiceImpl.*(..))")

3.对com.atguigu.dao包里面所有类,类里面所有方法进行增强。

@Before(value = "execution(* com.Huiex.*.*.*(..))")

配置不同类型的通知

l 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

前置通知 @Before

@Before注解表示作为前置通知

在这里插入图片描述

最终通知 @After

​ @After(相当于finally)

在这里插入图片描述

后置通知 @AfterReturning

在这里插入图片描述

异常通知 @AfterThrowing

在这里插入图片描述

环绕通知 @Around

在这里插入图片描述

不同通知顺序

@Before 在增强方法前面

@Around 在最前和最后

@AfterReturning 在增强方法后面

@After 在增强方法后面 在@AfterReturning后面 一定会触发

@AfterThrowing 出现异常后触发此通知,增强方法后的只会触发@Afte通知

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值