Spring 框架

1. 概念理解

1.1 Spring

Spring 是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。简化企业级开发,支持对框架的整合。

1.2 IOC 控制反转

IOC(Inversion of Control)控制反转:
是一种设计思想,由主动的创建变成被动的接收,即程序本身不创建对象,而是被动的接受对象;
控制是指由谁控制对象的创建,传统应用程序的对象是由程序本身控制对象的创建,而Spring 框架是由Spring 来创建,放到容器中,使用时从容器中取对象即可;

DI(Dependency Injection)依赖注入:
是实现IOC 的一种方法,就是对属性的注入(赋值),不用再管理对象的创建,大大降低了系统的耦合性,本质是利用Set 方法来进行注入。

1.3 AOP 面向切面编程

AOP(Aspect Oriented Programming)面向切面编程:
通过预编译方式动态代理实现程序功能的统一维护的一种技术。AOP 是OOP 的延续,而代理模式是Spring AOP 的底层。

开发工程中,部分代码与业务逻辑无关,但又需要使用他们,如事物、日志(前后)、缓存、安全等代码,利用AOP 就不必将这部分代码写入业务逻辑代码中。

1.4 框架整合

SSH:Struts + Spring + Hibernate
SSM:SpringMvc + Spring + Mybatis

Spring Boot:快速开发单个微服务,约定大于配置;
Spring Cloud:基于Spring Boot 实现的,协调整合微服务。

2. 代码理解 IOC

客户端 ⇒ Service ⇒ Dao 三层调用

导入jar 包:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>
    </dependencies>

2.1 传统写法

客户端调用Dao 层的具体操作时,需要Service 层创建Dao 对象,客户端再创建Service 对象,从而进行调用操作。

需求:获取 MySql 数据库连接。

// Dao 层
public interface JDBCDao {
    void getConnect();
}
public class MySqlDaoImpl implements JDBCDao {
    public void getConnect() {
        System.out.println("===MySqlDaoImpl===");
    }
}
// Service 层
public interface JDBCService {
    void getConnect();
}
public class JDBCServiceImpl implements JDBCService {
    private JDBCDao jdbcDao = new MySqlDaoImpl();
    public void getConnect() {
        jdbcDao.getConnect();
    }
}
// 客户端(测试类)
public class MyTest {
    public static void main(String[] args) {
        JDBCService jdbcService = new JDBCServiceImpl();
        jdbcService.getConnect();
    }
}

不便之处举例:
当需求变更,需要获取 Oracle 数据库连接时,Service 层需要从新创建Dao 实现类的对象。

// 增加Oracle 的 Dao 实现类
public class OracleDaoImpl implements JDBCDao {
    public void getConnect() {
        System.out.println("OracleDaoImpl Dao");
    }
}
// Service 层需要从新创建Dao 接口实现类对象 OracleDaoImpl()
public class JDBCServiceImpl implements JDBCService {
    // private JDBCDao jdbcDao = new MySqlDaoImpl();
    private JDBCDao jdbcDao = new OracleDaoImpl();
    public void getConnect() {
        jdbcDao.getConnect();
    }
}

2.2 普通代码的控制反转

Service 层不再控制Dao 对象的创建,而是交由调用者来创建,客户端与业务逻辑中关于操控对象的创建职责发生反转,顾称之为“控制反转”。从而大大降低了系统的耦合性。

// Service 层将不创建Dao 对象,而让调用者通过set 方法自行设置要调用的Dao 实现类对象
public class JDBCServiceImpl implements JDBCService {
    private JDBCDao jdbcDao;
    public void setJdbcDao(JDBCDao jdbcDao) {
        this.jdbcDao = jdbcDao;
    }
    public void getConnect() {
        jdbcDao.getConnect();
    }
}
// 客户端创建Dao 对象,并进行调用
public class MyTest {
    public static void main(String[] args) {
        JDBCService jdbcService = new JDBCServiceImpl();
        //((JDBCServiceImpl)jdbcService).setJdbcDao(new MySqlDaoImpl());
        ((JDBCServiceImpl)jdbcService).setJdbcDao(new OracleDaoImpl());
        jdbcService.getConnect();
    }
}

2.3 Spring 的控制反转

Spring 容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc 容器中取出需要的对象

通过XML 配置文件控制对象的创建。

2.3.1 简例

Hello 类

public class Hello {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Hello{" +
                "name='" + name + '\'' +
                '}';
    }
}

创建配置文件:resources/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="hello" class="com.chengyu.pojo.Hello">
        <!-- 属性赋值 -->
        <property name="name" value="Spring"/>
    </bean>
</beans>

客户端调用:从容器中取对象!

public class MyTest {
    public static void main(String[] args) {
        // 获取Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 对象在Spring 容器中管理,从容器中取对象
        Hello hello = (Hello)context.getBean("hello");
        System.out.println(hello.toString());
    }
}

2.3.2 将2.2 代码升级为Spring 管理

创建配置文件:resources/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">
    <!-- 创建Dao 对象 -->
    <bean id="mySqlDaoImpl" class="com.chengyu.dao.MySqlDaoImpl"/>
    <bean id="oracleDaoImpl" class="com.chengyu.dao.OracleDaoImpl"/>
    
    <bean id="jdbcServiceImpl" class="com.chengyu.service.JDBCServiceImpl">
        <!-- ref 引用Spring 中已经创建好的对象 -->
        <property name="jdbcDao" ref="oracleDaoImpl"/>
    </bean>
</beans>

客户端调用:

public class MyTest {
    public static void main(String[] args) {
        // 获取Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 对象在Spring 容器中管理,从容器中取对象
        JDBCServiceImpl jdbcService = (JDBCServiceImpl)context.getBean("jdbcServiceImpl");
        jdbcService.getConnect();
    }
}

3. Bean 管理(XML方式)

Bean 中主要做两件事,一是创建对象,二是注入属性。

3.1 创建对象

例:在Bean 中对Hello 类进行对象的创建。

public class Hello {
    private String name;
    public Hello() {
    }
    public Hello(String name) {
        this.name = name;
    }
    // set get 方法略
}

3.1.1 无参构造器(默认)

    <!-- 创建对象 -->
    <bean id="hello" class="com.chengyu.pojo.Hello"></bean>

3.1.2 有参构造器 - 下标赋值

    <!-- 创建对象 -->
    <bean id="hello" class="com.chengyu.pojo.Hello">
        <!-- 下标赋值 -->
        <constructor-arg index="0" value="chengyu"/>
    </bean>

3.1.3 有参构造器 - 类型赋值

    <!-- 创建对象 -->
    <bean id="hello" class="com.chengyu.pojo.Hello">
        <!-- 类型赋值 -->
        <constructor-arg type="java.lang.String" value="chengyu1"/>
    </bean>

3.1.4 有参构造器 - 参数名赋值

    <!-- 创建对象 -->
    <bean id="hello" class="com.chengyu.pojo.Hello">
        <!-- 参数名赋值 -->
        <constructor-arg name="name" value="chengyu2"/>
    </bean>

3.2 属性注入(赋值)DI - 手动装配

DI 依赖注入,是实现IOC 的一种方法,就是属性注入的意思。

3.2.1 构造器注入属性

【3.1】有参构造器创建时,对属性的注入。

3.2.2 Set 方法注入属性 ※

依赖:bean 对象的创建依赖于容器
注入:bean 对象中的所有属性,由容器来注入

public class Address {
    private String address;
	// set get 方法略
}
public class Person {
    private String name;
    private Address address;
    private String[] arrays;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;
    private Properties properties;
    private String bak;
	// set get 方法略
}
<?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="address" class="com.chengyu.pojo.Address">
        <property name="address" value="大连"/>
    </bean>

    <bean id="person" class="com.chengyu.pojo.Person">
        <!-- 字符串注入 -->
        <property name="name" value="chengyu3"/>
        <!-- bean 注入 -->
        <property name="address" ref="address"/>
        <!-- 数组 注入 -->
        <property name="arrays">
            <array>
                <value>aaaArr</value>
                <value>bbbArr</value>
                <value>cccArr</value>
            </array>
        </property>
        <!-- List 注入 -->
        <property name="list">
            <list>
                <value>aaaList</value>
                <value>bbbList</value>
            </list>
        </property>
        <!-- Map 注入 -->
        <property name="map">
            <map>
                <entry key="key1" value="value1"/>
                <entry key="key2" value="value2"/>
            </map>
        </property>
        <!-- Set 注入 -->
        <property name="set">
            <set>
                <value>aaaSet</value>
                <value>bbbSet</value>
            </set>
        </property>
        <!-- null 注入 -->
        <property name="bak">
            <null/>
        </property>
        <!-- Properties 注入 -->
        <property name="properties">
            <props>
                <prop key="学号">0907</prop>
                <prop key="性别"></prop>
            </props>
        </property>
    </bean>
</beans>
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Person person = (Person)context.getBean("person");
        System.out.println(person.toString());
    }

Person{name=‘chengyu3’, address=Address{address=‘大连’}, arrays=[aaaArr, bbbArr, cccArr], list=[aaaList, bbbList], map={key1=value1, key2=value2}, set=[aaaSet, bbbSet], properties={学号=0907, 性别=男}, bak=‘null’}

3.2.3 扩展方式注入

可以使用 p 命名空间和 c 命名空间注入。

public class User {
    private String name;
    private int age;
    public User() {}
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // set get 方法略
}
<?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">
    <!--p 命名空间注入,可以直接注入属性值-->
    <bean id="userP" class="com.chengyu.pojo.User" p:name="chengyu" p:age="30"/>
    <!--c 命名空间注入,可以直接注入构造器-->
    <bean id="userC" class="com.chengyu.pojo.User" c:name="chengwei" c:age="25"/>
</beans>
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User userP = (User)context.getBean("userP");
        System.out.println(userP);

        User userC = (User)context.getBean("userC");
        System.out.println(userC);
    }

3.3 属性注入(赋值)DI - 自动装配

自动装配:不用使用property 属性标签, 根据匹配的属性值进行注入。
Spring 会在上下文中自动寻找,并自动给bean 装配属性

例:一个人有两个宠物。

public class Cat {
    public void eat(){System.out.println("吃鱼");}
}
public class Dog {
    public void eat(){System.out.println("啃骨头");}
}
public class Person {
    private String name;
    private Cat cat;
    private Dog dog;
	// set get 方法略
}
    <bean id="cat" class="com.chengyu.pojo.Cat"/>
    <bean id="dog" class="com.chengyu.pojo.Dog"/>
    <bean id="person" class="com.chengyu.pojo.Person">
        <property name="name" value="chengyu"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>        
    </bean>
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Person person = (Person)context.getBean("person");
        person.getCat().eat();
        person.getDog().eat();
    }

3.3.1 自动装配:autowire=“byName”

会自动在容器上下文查找和自己对象set() 后面的值对应的 beanid。

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

    <bean id="person" class="com.chengyu.pojo.Person" autowire="byName">
        <property name="name" value="chengyu"/>
    </bean>

3.3.2 自动装配:autowire=“byType”

会自动在容器上线文查找和自己对象属性类型相同的 beanid。

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

    <bean id="person" class="com.chengyu.pojo.Person" autowire="byType">
        <property name="name" value="chengyu"/>
    </bean>

3.4 Bean 的作用域 scope

singleton 单例模式,默认。

	<bean id="address" class="com.chengyu.pojo.Address" scope="singleton">
        <property name="address" value="大连"/>
    </bean>

prototype 原型模式,每次从容器中 get 的时候,都是一个新对象。

    <bean id="address" class="com.chengyu.pojo.Address" scope="prototype">
        <property name="address" value="大连"/>
    </bean>

request、session、application 只能在web 开发中使用。

3.5 补充

3.5.1 起别名-alias方式

    <bean id="hello" class="com.chengyu.pojo.Hello">
        <constructor-arg name="name" value="chengyu2"/>
    </bean>

    <alias name="hello" alias="hi"/>
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 对象在Spring 容器中管理,从容器中取对象
        //Hello hello = (Hello)context.getBean("hello");
        Hello hello = (Hello)context.getBean("hi");
        System.out.println(hello.toString());
    }

3.5.2 起别名-name方式

name 属性也可以起别名,而且可以多个。

    <bean id="hello" class="com.chengyu.pojo.Hello" name="hi,hell">
        <constructor-arg name="name" value="chengyu2"/>
    </bean>

3.5.3 合并配置文件 import

一般用于团队开发使用,可以将多个配置文件导入并合并。

applicationContext.xml 中导入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">

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

4. Bean 管理(注解方式)

Bean 中主要做两件事,一是创建对象,二是注入属性。

前提
1)Spring2.5 开始支持,在Spring4 之后,要使用注解开发,必须导入 aop 包。(aspectjweaver 包中已包含)
2)开启组件扫描:

http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
<context:annotation-config/>

4.1 创建对象 Component

@Component
等价于创建了一个bean,即创建对象。
<bean id=“user” class=“com.chengyu.pojo.User”/>

@Component
public class User {
}

衍生注解:功能相同,仅为了提示代码所处的层不同。
dao:@Repository
service:@Service
controller:@Controller

@Repository
public class UserDao {
}
@Service
public class UserService {
}
@Controller
public class UserController {
}

这四个注解的功能是一样的,都是将某个类注册到Spring 容器中,装配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"
       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/>
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.chengyu"/>
</beans>

4.2 属性注入DI - 手动装配

@Value:

    // 等价于 bean 中的属性注入 <property name="name" value="chengyu"/>
    @Value("chengyu")
    public void setName(String name) {
        this.name = name;
    }

4.3 属性注入DI - 自动装配

4.3.1 Autowired

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

    <bean id="cat" class="com.chengyu.pojo.Cat"/>
    <bean id="dog" class="com.chengyu.pojo.Dog"/>
    <bean id="person" class="com.chengyu.pojo.Person"/>

@Autowired

public class Person {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    // set get 方法略
}
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Person person = (Person)context.getBean("person");
        person.getCat().eat();
        person.getDog().eat();
    }

补充:
1)@Autowired 可以和 @Qualifier(value = “cat”) 搭配使用,指明唯一的bean 对象注入。

    @Autowired
    @Qualifier(value = "cat")
    private Cat cat;

2)@Resource 根据Type 查找。类型重复时,也可指定名称 @Resource(name=“cat2”)

4.3.2 Resource

import javax.annotation.Resource;
Java 的注解,只要名称或类型有一个一致,即可成功注入;
Resource 中也可以指定名称。

    <bean id="cat" class="com.chengyu.pojo.Cat"/>
    <bean id="dog" class="com.chengyu.pojo.Dog"/>
    <bean id="person" class="com.chengyu.pojo.Person"/>
public class Person {
    private String name;
    @Resource
    private Cat cat;
    @Resource(name = "dog")
    private Dog dog;
    // set get 方法略
}

4.4 作用域 Scope

@Controller
@Scope("singleton")
public class UserController {
}

4.5 XML与注解比较

XML 更万能,适用于任何场合,维护简单方便;
注解:不是自己的类使用不了,相对复杂。

推荐:XML 管理Bean,注解实现属性的注入。

注意:使用注解必须先让开启注解支持,并扫描到该注解所在的包。

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

5. 纯Java 装配

在Spring 中有三种装配方式:
1)手动装配
2)自动装配
3)Java 中显示装配

完全不需要配置文件,Spring4 之后,javaConfig 成为核心功能。

@Component:将类注册到Spring 容器中。

@Component
public class User {
    private String name;
    public String getName() {
        return name;
    }
    @Value("chengyu")
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

@Configuration:注明这是一个配置类,等同于beans.xml
@Bean:相当于一个bean 标签,方法名相当于 id,返回值是要注入的bean 对象

@Configuration
@ComponentScan("com.chengyu.pojo")
public class ChengConfig {
    @Bean
    public User getUser(){
        return new User();
    }
}
    public void test01(){
        ApplicationContext context = new AnnotationConfigApplicationContext(ChengConfig.class);
        User user = (User) context.getBean("getUser");
        System.out.println(user.getName());
    }

6. 代码理解 AOP

6.1 API 接口方式

public class Log implements MethodBeforeAdvice, AfterReturningAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    }

    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + method.getName() + ",返回结果为:" + returnValue);
    }
}

业务逻辑:

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

public class UserServiceImpl implements UserService
{
    public void add() {
        System.out.println("添加一个用户");
    }
    public void delete() {
        System.out.println("删除一个用户");
    }
    public void update() {
        System.out.println("更新一个用户");
    }
    public void select() {
        System.out.println("查询一个用户");
    }
}

applicationContext.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: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">

    <!--注册 bean-->
    <bean id="userService" class="com.chengyu.service.UserServiceImpl"/>
    <bean id="log" class="com.chengyu.log.Log"/>

    <!--方式一:使用原生Spring API接口-->
    <!--配置aop:需要导入aop 的约束-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.chengyu.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    </aop:config>

</beans>
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

com.chengyu.service.UserServiceImpl的add被执行了
添加一个用户
执行了add,返回结果为:null

6.2 自定义类方式

public class DiyPointCut {
    public void before(){
        System.out.println("方法执行前");
    }
    public void after(){
        System.out.println("方法执行后");
    }
}

业务逻辑:

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}
public class UserServiceImpl implements UserService
{
    public void add() {
        System.out.println("添加一个用户");
    }
    public void delete() {
        System.out.println("删除一个用户");
    }
    public void update() {
        System.out.println("更新一个用户");
    }
    public void select() {
        System.out.println("查询一个用户");
    }
}
<?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">

    <!--注册 bean-->
    <bean id="userService" class="com.chengyu.service.UserServiceImpl"/>
    <bean id="log" class="com.chengyu.log.Log"/>

    <!--方式二:自定义类-->
    <bean id="diy" class="com.chengyu.diy.DiyPointCut"/>
    <aop:config>
        <!--自定义切面:ref 要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.chengyu.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

MyTest 执行结果:
方法执行前
添加一个用户
方法执行后

6.3 注解方式

@Aspect // 标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.chengyu.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }
    @After("execution(* com.chengyu.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }
    // 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.chengyu.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable { // 可以从切入点中获取东西
        System.out.println("环绕前");
        System.out.println(jp.getSignature());// 获取签名
        // 执行
        Object SS = jp.proceed();
        System.out.println("环绕后");
    }
}

业务逻辑:

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}
public class UserServiceImpl implements UserService
{
    public void add() {
        System.out.println("添加一个用户");
    }
    public void delete() {
        System.out.println("删除一个用户");
    }
    public void update() {
        System.out.println("更新一个用户");
    }
    public void select() {
        System.out.println("查询一个用户");
    }
}

MyTest 执行结果:
环绕前
void com.chengyu.service.UserService.add()
方法执行前
添加一个用户
方法执行后
环绕后

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值