【JAVAEE框架】浅谈 AOP 及代码实现

 哈喽~大家好呀,上篇讲到 Spring 框架的两大核心思想 AOP 与 IOP的原理,现在来看看具体代码实现。

 🥇个人主页:个人主页​​​​​             

🥈 系列专栏:【云原生系列】

🥉与这篇相关的文章:            

【JAVAEE框架】Spring 项目构建流程

【JAVAEE框架】Spring 项目构建流程_程序猿追的博客-CSDN博客

【JAVAEE框架】Mybatis常用操作(CRUD)

【JAVAEE框架】Mybatis常用操作(CRUD)_程序猿追的博客-CSDN博客

Java测试、反射、注解

Java测试、反射、注解_程序猿追的博客-CSDN博客

目录

一、前言

1、实现需要的知识点

2、定义切入点

二、原生代码实现

 三、注解实现

1、注解

2、Spring AOP配置元素

3、注解实现


一、前言

上篇讲到 AOP 它是基于代理模式下进行的,这篇来讲讲代码是如何实现。

1、实现需要的知识点

AspectJ 中常用的通知有四种类型:

(1)前置通知

(2)后置通知

(3)环绕通知

(4)最终通知

(5)定义切入点

2、定义切入点

切入点:简单的说,就是连接点的查询条件

示例

<aop:config>
<aop:pointcut id="pointcut"
            expression="execution(public void addNewUser(entity.User))"/>
</aop:config>

表达式匹配规则举例

public * addNewUser(entity.User): “*”表示匹配所有类型的返回值。
public void *(entity.User): “*”表示匹配所有方法名。
public void addNewUser(..): “..”表示匹配所有参数个数和类型。
* com.service.*.*(..):匹配com.service包下所有类的所有方法。
* com.service..*.*(..):匹配com.service包及其子包下所有类的所有方法

二、原生代码实现

pom导入 aop 需要的依赖

        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>

创建 userService.java

用来做方法测试类

public class UserService {

    public Integer addUser(int n) {
        Integer r = 0;

        r = 100 / n;
        System.out.println("addUser 运行了");
        System.out.println(r);

        return r;
    }

    public int deleteUser(String id) {
        System.out.println("删除:" + id);
        return 1;
    }

}

编写 UserAspect.java

    // 前置通知
    // JoinPoint: 连接点,改对象包含目标方法的相关信息
    public void before(JoinPoint jp){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法执行了,参数: " + Arrays.toString(jp.getArgs()));
    }

    // 后置通知
    public void after(JoinPoint jp){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "之后方法执行了,参数: " + Arrays.toString(jp.getArgs()));
    }

    // 异常通知
    public void errorNation(JoinPoint jp, Throwable e){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法出错了,错误是: " + e.getMessage());
    }

    // 返回通知

    public void ReturnNation(JoinPoint jp, Object ret){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法的返回结果是: " + ret);
    }

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

	<bean id="UserAspect" class="com.itxzw.user.UserAspect"/>

	<bean id="UserService" class="com.itxzw.user.UserService"/>

	<aop:config>

		<aop:pointcut id="pointcut" expression="execution(public * com.itxzw.user.UserService.*(..))"/>

		<aop:aspect ref="UserAspect">
			<aop:before method="before" pointcut-ref="pointcut"/>
			<aop:after method="after" pointcut-ref="pointcut"/>
			<aop:after-throwing method="errorNation" throwing="e" pointcut-ref="pointcut"/>
			<aop:after-returning method="ReturnNation" returning="ret" pointcut-ref="pointcut"/>

<!--			<aop:around method="roundNation" pointcut-ref="pointcut"/>-->
		</aop:aspect>

	</aop:config>

</beans>

 编写测试类

    @Test
    public void Test01(){

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

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

        userService.addUser(10);

        System.out.println(userService);

    }

效果

底层原理就是采用了代理模式

 三、注解实现

1、注解

前置通知@Before:前置增强处理,在目标方法前织入增强处理

后置通知@AfterReturning:后置增强处理,在目标方法正常执行(不出现异常)后织入增强处理

环绕通知@Around:环绕增强处理,在目标方法的前后都可以织入增强处理

最终通知@After:最终增强处理,不论方法是否抛出异常,都会在目标方法最后织入增强处理

异常通知@AfterThrowing:异常增强处理,在目标方法抛出异常后织入增强处理

定义切入点@Pointcut

2、Spring AOP配置元素

 3、注解实现

注解方式将Bean的定义信息和Bean实现类结合在一起,Spring提供的注解有
@Component:实现Bean组件的定义
@Repository    :用于标注DAO类
@Service    :用于标注业务类
@Controller    :用于标注控制器类

@Repository("userDao") 
public class UserDaoImpl implements UserDao {
    …
}
与在XML配置文件中编写
<bean id="userDao" 
class="dao.impl.UserDaoImpl" /> 
等效
 

使用@Autowired注解实现Bean的自动装配,默认按类型匹配,可以使用@Qualifier指定Bean的名称

@Service("userService") 
public class UserServiceImpl implements UserService { 
    @Autowired
    @Qualifier("userDao")
    private UserDao dao; 
    …… 
}

可以对类的成员变量进行标注
@Service("userService") 
public class UserServiceImpl implements UserService { 
    private UserDao dao;
    @Autowired
    public void setDao((@Qualifier("userDao") UserDao dao) {
       this.dao = dao;
    } 
  …… 
}

也可以对方法的入参进行标注

使用注解信息启动Spring容器

<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/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- 扫描包中注解标注的类 -->
    <context:component-scan base-package="service,dao" />
</beans>

指定需要扫描的基类包,多个包可用逗号隔开

示例

UserAspect.java

@Component
@Aspect
public class UserAspect {

    // 定义切入点
    @Pointcut("execution(public * com.itxzw..*.*(..))")
    public void pointcut(){}

    // 前置通知
    // JoinPoint: 连接点,改对象包含目标方法的相关信息
    @Before("pointcut()")
    public void before(JoinPoint jp){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法执行了,参数: " + Arrays.toString(jp.getArgs()));
    }

    // 后置通知
    @After("pointcut()")
    public void after(JoinPoint jp){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "之后方法执行了,参数: " + Arrays.toString(jp.getArgs()));
    }

    // 异常通知
    @AfterThrowing(pointcut = "pointcut()", throwing = "e")
    public void errorNation(JoinPoint jp, Throwable e){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法出错了,错误是: " + e.getMessage());
    }

    // 返回通知
    @AfterReturning(pointcut = "pointcut()", returning = "ret")
    public void ReturnNation(JoinPoint jp, Object ret){
        System.out.println(jp.getTarget() + "的" + jp.getSignature().getName() + "方法的返回结果是: " + ret);
    }

    // 环绕通知
    @Around("pointcut()")
    public void roundNation(ProceedingJoinPoint jp){
        Object t = jp.getTarget();
        String name = jp.getSignature().getName();
        String args = Arrays.toString(jp.getArgs());
        Object rel;

        try {
            System.out.println(t + "的" + name + "方法执行了,参数是:" + args);

            rel = jp.proceed(jp.getArgs());

            System.out.println(t + "的" + name + "方法结果是:" + rel);
        }catch (Throwable e){
            System.out.println(t + "的" + name + "方法出错了:" + e.getMessage());
        }finally {
            System.out.println(t + "的" + name + "方法结束了");
        }
    }

}

UserService.java

@Component(value = "userService")
public class UserService {

    public Integer addUser(int n) {
        Integer r = 0;


        r = 100 / n;
        System.out.println("addUser 运行了");
        System.out.println(r);

        return r;
    }

    public int deleteUser(String id) {
        System.out.println("删除:" + id);
        return 1;
    }

}

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: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-4.0.xsd
	   http://www.springframework.org/schema/aop
	   http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
	   http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.2.xsd">


<!--xmlns:context="http://www.springframework.org/schema/context"-->

<!--	<bean id="address" class="com.itxzw.user.model.Address">-->

<!--	</bean>-->

<!--	开启扫描-->
	<context:component-scan base-package="com.itxzw.user" />

<!--	开启Aspect生成代理对象-->
	<aop:aspectj-autoproxy proxy-target-class="false"/>

</beans>

测试

    @Test
    public void test02(){

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

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

        userService.addUser(10);

    }

效果

不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!

  • 33
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 25
    评论
### 回答1: 石毅是一位Java EE框架开发者,他的代码示例非常有价值。下面我将用300字回答有关石毅代码示例的问题。 石毅的代码示例涵盖了Java EE框架的各个方面,包括Web开发、数据库访问、事务管理和安全性等。他的代码示例非常简洁而且易于理解,让人们能够很快上手。 首先,他展示了如何使用Java EE框架进行Web开发。他使用了Servlet和JSP来创建动态网页,并且演示了如何获取用户输入、处理请求和生成响应。他还展示了使用标准标签库(JSTL)和EL表达式来简化JSP页面的开发过程。 其次,石毅还展示了如何使用Java EE框架进行数据库访问。他使用了JDBC和连接池技术来连接和操作数据库,并且演示了如何执行查询、更新和事务处理。他的代码示例还包括了如何使用ORM(对象-关系映射)框架来简化数据库操作。 此外,石毅还对Java EE框架的事务管理功能进行了示例。他展示了如何使用注解和XML配置来管理事务,包括声明式和编程式事务的使用方式。他的代码示例还演示了如何处理事务的并发和回滚操作。 最后,石毅的代码示例还包括了Java EE框架的安全性方面的内容。他展示了如何使用容器(如Tomcat)的安全机制来保护Web应用,并且演示了如何使用基于角色的访问控制(RBAC)和表单验证来控制用户的访问权限。 总的来说,石毅的代码示例涵盖了Java EE框架的重要组成部分,并且通过简洁而实用的代码展示了如何使用这些功能来开发高质量的Web应用。对于正在学习和使用Java EE框架的开发者来说,这些代码示例无疑是非常宝贵的学习资源。 ### 回答2: 石毅代码示例是指作者石毅编写的一些JavaEE框架的示例代码。石毅是一个经验丰富的程序员,他根据自己多年的开发经验,总结归纳出一套高效、易用的JavaEE框架。 这些示例代码涵盖了JavaEE框架的多个方面,包括Web开发、ORM(对象关系映射)、事务管理、并发处理、安全性等。石毅代码示例可以帮助开发人员更好地理解和应用JavaEE框架,提高开发效率和质量。 以Web开发为例,石毅代码示例提供了一套简洁而强大的Web框架,可以快速构建JavaEE应用程序。示例代码包括处理请求和响应、路由分发、会话管理、表单验证和文件上传等功能。开发人员可以根据示例代码来学习和使用这个Web框架,从而快速搭建自己的Web应用。 另外,石毅的代码示例还包括了ORM框架的应用,这可以帮助开发人员简化数据库操作和对象关系映射的工作。示例代码展示了如何定义实体类、进行增删改查操作、使用查询语言和配置文件等。开发人员可以根据示例代码学习和使用ORM框架,提高数据库操作的效率。 总的来说,石毅代码示例是一份宝贵的学习资料,可以帮助开发人员更好地掌握JavaEE框架的开发技巧和最佳实践。无论是初学者还是有经验的开发人员,都可以从中受益,提升自己的技术水平。 ### 回答3: 石毅代码示例是一个基于JavaEE框架的示例代码,它展示了一些常见的JavaEE开发中的功能和用法。 首先,石毅代码示例包含了使用Servlet的示例。Servlet是JavaEE开发中的基本组件之一,它可以处理HTTP请求和响应。示例中展示了如何创建一个Servlet,并实现doGet和doPost方法来处理GET和POST请求。 其次,示例中也包含了使用JSP的示例。JSP是JavaEE开发中的模板引擎,可以将Java代码嵌入到HTML页面中。示例展示了如何创建一个简单的JSP页面,并使用标签库来显示动态数据。 此外,示例中还涵盖了使用JDBC的示例。JDBC是JavaEE开发中用于与数据库交互的API。示例展示了如何连接到数据库、执行SQL查询和更新操作,并处理结果集。 另外,示例中还包含了使用Hibernate的示例。Hibernate是JavaEE开发中的ORM框架,可以将Java对象映射到数据库表中。示例展示了如何定义实体类、配置Hibernate并执行基本的增删改查操作。 最后,石毅代码示例还包含了使用Spring框架的示例。Spring是一个开源的JavaEE开发框架,可以简化JavaEE开发的配置和管理。示例展示了如何使用Spring框架来管理依赖注入、事务管理等功能。 总之,石毅代码示例是一个全面展示了JavaEE开发中常见功能和用法的示例代码,对于想要学习或了解JavaEE开发的人来说是一个很好的参考。
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿追

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

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

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

打赏作者

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

抵扣说明:

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

余额充值