spring 04 实现简单的aop

Aop 的好处:
1.使得真实角色处理的业务更加纯粹。不再去关注一些公共的事情。
2.公告的业务由代理来完成。。实现业务分工
3.公共业务发生扩展时变得更加集中和方便。
名词及解释:
关注点:增加的某个业务,如日志,安全,事务等。
切面:关注点的模块化。(将日志,安全写成单独的类,该类称为切面)
连接点:表示一个方法的执行。
通知:在切面的某个特定的连接点上执行的动作。
目标对象:被代理的对象就是目标对象。
织入:把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象。

实现方式:

第一步 增加maven依赖
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.spring</groupId>
  <artifactId>spring04_aop</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
    <!--版本管理-->
  <properties>
  	 <spring.version>4.1.3.RELEASE</spring.version>
  	 <aspectj.version>1.6.11</aspectj.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
 
<!--测试包,自动生成-->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!--spring aop依赖-->
      <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
	</dependency>
	<!--spring上下文包,在加载spring配置文件时用到-->
	  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
	</dependency>
    <!--使用AspectJ方式注解需要相应的包-->
      <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
         <!--使用AspectJ方式注解需要相应的包-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    
  </dependencies>
</project>

第二步 编写UserDao接口
UserDao.java

package org.spring04;

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

第三步 编写UserDaoImpl类,该类实现UserDao接口。
UserDaoImpl.java

package org.spring04;

/**
 * 用户类(领域业务对象类)
 * @author yxl
 *
 */
public class UserDaoImpl implements UserDao {
	public void add() {
		System.out.println("增加了一个用户!");
	}
	public void delete() {
		System.out.println("删除了一个用户!");
	}
}

第四步 编写切面类 (公共业务类)Log。需实现下列接口。
实现接口MethodBeforeAdvice该拦截器会在调用方法前执行
实现接口 AfterReturningAdvice该拦截器会在调用方法后执行
实现接口 MethodInterceptor该拦截器会在调用方法前后都执行,实现环绕结果。
Log.java

package org.spring04;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

/**
	切面类 (公共业务类)
	实现接口MethodBeforeAdvice该拦截器会在调用方法前执行
	实现接口   AfterReturningAdvice该拦截器会在调用方法后执行
	实现接口  MethodInterceptor该拦截器会在调用方法前后都执行,实现环绕结果。
 */
public class Log implements MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor{

	/**
	 * 前置通知
	 * @param method 被调用对象的方法
	 * @param args  被调用的方法参数
	 * @param target 被调用的方法的目标对象
	 */
	public void before(Method method, Object[] arg1, Object target) throws Throwable {
		System.out.println("前置通知:"+target.getClass().getName()+" 的 "+method+"方法被调用了。");
	}
	
	/**
	 * 后置通知
	 */
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
		System.out.println("后置通知");
	}

	/**
	 * 环绕通知
	 */
	public Object invoke(MethodInvocation arg0) throws Throwable {
		System.out.println("环绕通知开始");
		Object result=arg0.proceed();
		System.out.println("环绕通知结束");
		return result;
	}
	
}

第五步 编写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"
       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-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop            
           http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
           ">
           
    <bean id="userDaoImpl" class="org.spring04.UserDaoImpl"/>
    <bean id="log" class="org.spring04.Log"></bean>
    <aop:config>
		<!-- 配置(连接点)关注点。指哪些业务方法需要增加公共的功能方法。 expression:匹配规则,,匹配要织入领域对象的范围。
		第一个*代表返回值。
		参数括号里面的两个..  表示所有参数。 -->
		<aop:pointcut id="pointcut" expression="execution(public * org.spring04.*.*(..))" />
		<!-- 配置切面(公共函数) -->
		<aop:advisor advice-ref="log" pointcut-ref="pointcut" />
	</aop:config>
	

</beans>

第六步 编写测试类

Test.java

package org.spring04;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	
	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
		UserDao userDao = (UserDao) app.getBean("userDaoImpl");
		userDao.add();

	}
}

注意: UserDao userDao = (UserDao) app.getBean(“userDaoImpl”);
强制转换的时候必须使用父类类型进行强转。否则动态代理生成的类无法转换到我们自定义的实现类。

错误写法: UserDao userDao = (UserDaoImpl) app.getBean(“userDaoImpl”);
错误提示:com.sun.proxy.$Proxy2 cannot be cast to org.spring04.UserDaoImpl

控制台结果:

环绕通知开始
前置通知:org.spring04.UserDaoImpl 的 public abstract void org.spring04.UserDao.add()方法被调用了。
增加了一个用户!
后置通知
环绕通知结束

猜你喜欢

转载自blog.csdn.net/shenlanse7626/article/details/84098441
今日推荐