spring02:使用注解完成IOC配置、依赖注入以及AOP面向切面编程(上)


前言

前面讲了如何使用配置文件实现控制反转和依赖注入。jar包里的类只能在配置文件中进行配置,但自己写的类可以使用注解来完成配置。下面就讲一下如何使用注解实现控制反转和依赖注入。并且开始学习AOP面向切面编程。


一、使用注解完成IOC配置

使用注解将类转为bean组件,并将其添加到spring容器中。

1. 添加配置文件

spring配置文件增加context命名空间与xsd的引用,使用注解,需要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: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">

	<!--使用注解的方式为类配置成spring的bean组件,前提是需要启动扫描写注解的包-->
	<!--通过扫描base-Package下的包,将包下的组件添加到spring容器中-->
	<context:component-scan base-package="com"></context:component-scan>

</beans>

2. 将类转为bean组件的四种注解

这四种注解都可以将类变为bean组件,由spring容器创建和维护。区别在于这四种方式用来标识不同的层。

注解作用
@Repository用来标注持久层
@Service用来标注业务逻辑层
@Controller用来标注控制层
@Component如果不确定是哪一层,就用这个注解来标注

如果不在注解中注入id,则默认值为当前类首字母小写

3. Component注解

3.1 Component设置id

在这里插入图片描述
在这里插入图片描述
说明创建了Dog对象,转为spring组件后,由spring容器来创建和管理对象。

3.2 Component不设置id

不写id。默认id就是类名,首字母小写。
在这里插入图片描述
在这里插入图片描述
说明创建了Boy对象。

3.3 测试完整代码

public class DogTest {
    //这里创建静态容器对象
    //这个是spring对象,这个对象不能调用close方法
    //private static ApplicationContext ac = null;
    //这个是spring实现类对象,可以调用close方法关闭容器
    private static ClassPathXmlApplicationContext ac = null;
    static {
        ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
    /*使用注解*/
    @Test
    public void testDog01() {
        Dog dog = (Dog) ac.getBean("dog");
        System.out.println(dog);
    }
    @Test
    public void testBoy02() {
        Boy boy = (Boy) ac.getBean("boy");
        System.out.println(boy);
    }

}

二. 使用注解在类里实现依赖注入

依赖注入,实现为属性赋值。

1. 基本数据类型+其包装类+String

注解作用
@Value(“属性值”)为属性注入值

在这里插入图片描述
在这里插入图片描述

2. 对象

注解作用
@Resource(name = “dog”)相当于ref引入外部bean,给对象赋值
@Autowired按对象的数据类型自动注入(用的比较多)

在这里插入图片描述
在这里插入图片描述

三、使用properties文件实现注入

依赖注入一般不直接写在类里,而是写在properties文件呢里。这样方便对属性的管理。

1. 在添加properties文件之前先设置一下编码

在这里插入图片描述
在这里插入图片描述

2. 创建properties文件

这个是JavaEE项目。在src下新建properties文件。
在这里插入图片描述

3. msg.properties

map和properties集合使用的是键值对,采用JSON来写。

属性文件代码:

dogname=小黑
dogage=3
boyname=小敏
boyage=20
jobs=学生,程序员
hobbies=游泳,跑步
language={'zh':'中文','en':'English'}

4. spring如何获取properties文件里的属性

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

	<!--使用注解的方式为类配置成spring的bean组件,前提是需要启动扫描写注解的包-->
	<!--扫描包下的组件,将其添加到spring容器中-->
	<context:component-scan base-package="com"></context:component-scan>

	<!--引入properties文件共spring使用-->
	<context:property-placeholder location="msg.properties"></context:property-placeholder>

</beans>

5. 使用${}表达式注入值

5.1 基本数据类型+其包装类+String

在这里插入图片描述
在这里插入图片描述

5.2 对象

在这里插入图片描述
在这里插入图片描述

5.3 array、list、set

array:
在这里插入图片描述
list、set:需要用split将字符串通过逗号分隔为数组,然后用ognl表达式做数据类型转换
在这里插入图片描述

5.4 map、properties集合

需要用#{}做数据类型转换。如果出现错误,在注解没有写错的情况下,可以看一下properties文件里的键值是不是写错了。
在这里插入图片描述


第二部分内容:AOP面向切面编程


一、AOP面向切面编程

1. 什么是AOP

AOP(aspect oriented programming)
如果有一些功能方法(切入点),他们如果具有相同的功能。可以将通用的功能单独写成一个方法(切面)。通过AOP可以实现当切入点执行时,切面程序会植入到切入点方法里的某个位置(通知)执行,这个位置叫做通知。这就是面向切面编程。

2. AOP的优势

AOP好处:对一些具有通用功能的业务方法进行统一处理(由切面统一处理)

3. 通知的种类

组件是spring管理的一个bean对象,bean里的方法才可以作为切入点

3.1 前置通知

切面在目标组件的切入点正确执行之前先执行。

3.2 后置通知

切面在目标组件的切入点正确执行之后先执行。

3.3 异常通知

切面在目标组件的切入点发生异常时执行。

3.4 最终通知

不管目标组件的切入点是否能正确执行,切面都一定会执行。

二、AOP编程

1. 新建JavaSE项目,导入jar包

在这里插入图片描述

2. applicationContext.xml

添加配置文件

①扫描包,并将包下的bean组件添加到spring容器中
②启动aspectj的自动代理后,才可以将该切面添加到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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 开启自动扫描,扫描base-package指定的包下的类,如果是bean组件,就将其注入到spring容器中 -->
    <context:component-scan base-package="com"></context:component-scan>
    <!-- spring中使用aspectj包中的@Aspect注解标注当前组件为切面,
           如果要使用该注解必须开启aspectj的自动代理模式 -->
    <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
</beans>

3. 前置通知

不管是切入点还是切面都是spring容器里的组件里的方法,所以要设置切入点切面首先要将其设置为bean组件

如果要设置切面的话还需要 @Aspect,该注解让类里的方法可以设置为切面

这里只是简单的模拟一下使用面向切面编程。

3.1 DeptDao

自定义切入点方法。

package com.dao;

import org.springframework.stereotype.Repository;

@Repository
public class DeptDao {
    public Integer insert(String dname) {
        System.out.println(dname + "插入成功!");
        return 1;
    }

    public Integer update(String dname) {
        System.out.println(dname + "修改成功!");
        return 1;
    }
}

3.2 DmlAspect

该文件用来写切面程序。

含义/作用
@Component将该类添加到spring容器里,设置为bean组件;
@Aspect允许将类里的方法设置为切面;
@Before将类里的方法设置为前置通知
execution切入点表达式,用来指定切入点
JoinPoint切入点对象
package com.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class DmlAspect {
    // 前置通知的切面方法
    @Before("execution(* com.dao.*.*(*))")  //在注解里写切入点表达式
    public void doBefore(JoinPoint point) {
        System.out.println("**************前置通知**************");
        System.out.println("拦截切入点的第一个参数:" + point.getArgs()[0]);
        System.out.println("切入点方法原型:" + point.getSignature());
        System.out.println("切入点所属对象:" + point.getTarget());
        System.out.println("**********************************");
    }
}

在这里插入图片描述
切入点方法的参数类型和数目都不一定:
在这里插入图片描述
在这里插入图片描述
在注解里写切入点表达式,符合该表达式的类里的方法都可以作为切入点。
在这里插入图片描述
execution是切入点表达式,用来指定切入点。切入点的返回值类型包名类名方法名参数数目和类型。(重点:后面会详解
在这里插入图片描述
在这里插入图片描述

3.3 DeptTest

①创建spring容器
②通过spring容器获取bean组件对象
③通过bean组件来调用方法,执行切入点
④切入点在执行时,切面程序会监测到切入点的执行

package com.test;

import com.dao.DeptDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DeptTest {
    private static ApplicationContext as = null;

    static {
        as = new ClassPathXmlApplicationContext("applicationContext.xml");
    }

    @Test
    public void testDept() {
        DeptDao deptDao = (DeptDao) as.getBean("deptDao");
        deptDao.insert("开发部");
    }
}

4. 后置通知

4.1 DmlAspect

含义/作用
@AfterReturning将方法设置为前置通知
pointcut用来指定可以运行的切入点
returning用来获取切入点的返回值
 	// 后置通知的切面方法,它是在切入点成功执行之后才会执行该切面方法
    @AfterReturning(pointcut = "execution(* com.dao.*.*(*))", returning = "result")
    public void afterReturning(JoinPoint point, Object result) {
        System.out.println("**************后置通知******************");
        System.out.println("拦截切入点的第一个参数:" + point.getArgs()[0]);
        System.out.println("切入点方法原型:" + point.getSignature());
        System.out.println("切入点所属对象:" + point.getTarget());
        System.out.println("*********************************");
    }

这里需要注意的是如果目标组件(切入点)发生异常,后置通知就不会执行。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了如何使用注解创建bean对象,以及实现依赖注入。还讲解了什么是AOP面向切面编程,以及前置插入和后置插入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员_动次动次

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值