JavaEE(SSM)企业应用实战 chapter08

一、AOP实现机制

1、JDK动态代理

(1)接口 LoginService
package com.qf.chapter08.demo01;
​
public interface LoginService {
    public void login();
}
(2)接口实现类 LoginServiceImpl
package com.qf.chapter08.demo01;
​
public class LoginServiceImpl implements LoginService {
    public void login() {
        System.out.println("执行login()方法");
    }
}
(3)PerformHandler.java
package com.qf.chapter08.demo01;
​
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
​
public class PerformHandler implements InvocationHandler {
    // 目标对象
    private Object target;
​
    public PerformHandler(Object target) {
        this.target = target;
    }
​
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 增强的方法
        System.out.println("方法开始执行");
        // 执行被代理类的原方法
        Object invoke = method.invoke(target, args);
        // 增强的方法
        System.out.println("方法执行完毕");
        return invoke;
    }
}
(4)测试类 TestPerformHandler
package com.qf.chapter08.demo01;
​
import java.lang.reflect.Proxy;
​
public class TestPerformHandler {
    public static void main(String[] args) {
        LoginService loginService = new LoginServiceImpl();
        PerformHandler performHandler = new PerformHandler(loginService);
        // 创建代理对象
        loginService = (LoginService) Proxy.newProxyInstance(loginService.getClass().getClassLoader(),
                loginService.getClass().getInterfaces(), performHandler);
        loginService.login();
    }
}

2、CGLib动态代理

(1)CglibProxy.java
package com.qf.chapter08.demo01;
​
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.*;
​
public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
​
    // 生成代理对象的方法
    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
​
    // 回调方法
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLig代理之前");
        Object invoke = methodProxy.invokeSuper(obj, objects);
        System.out.println("CGLig代理之后");
        return invoke;
    }
}
(2)测试类
package com.qf.chapter08.demo01;
​
public class TestCGLlib {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        // 创建代理对象
        LoginServiceImpl userService = (LoginServiceImpl) cglibProxy.getProxy(LoginServiceImpl.class);
        userService.login();
    }
}

二、Spring AOP的开发方法

1、基于XML开发Spring AOP

(1)修改 applicationContext.xml ,引入 AOP 命名空间
<?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">
    
</beans>
(2)创建接口
package com.qf.chapter08.demo02;
​
public interface UserService {
    void insert();
​
    void delete();
​
    void update();
​
    void select();
}
(3)创建接口实现类
package com.qf.chapter08.demo02;

public class UserServiceImpl implements UserService {

	public void insert() {
		System.out.println("添加用户信息");
	}
	
	public void delete() {
		System.out.println("删除用户信息");
	}

	public void update() {
		System.out.println("更新用户信息");
	}

	public void select() {
		System.out.println("查询用户信息");
	}
}
(4)创建通知类
package com.qf.chapter08.demo02;

import org.aspectj.lang.ProceedingJoinPoint;

public class XmlAdvice {
	// 前置通知
	public void before() {
		System.out.println("这是前置通知");
	}

	// 后置通知
	public void afterReturning() {
		System.out.println("这是后置通知(方法不出现异常时调用)");
	}

	// 环绕通知
	public Object around(ProceedingJoinPoint point) throws Throwable {
		System.out.println("这是环绕通知之前的部分!!");
		// 调用目标方法
		Object object = point.proceed();
		System.out.println("这是环绕通知之后的部分!!");
		return object;
	}

	// 异常通知
	public void afterException() {
		System.out.println("异常通知!!");
	}

	// 后置通知
	public void after() {
		System.out.println("这是后置通知!!");
	}
}
(5)修改 applicationContext.xml ,添加 AOP 配置信息
	<!-- 注册Bean -->
	<bean name="userService" class="com.qf.chapter08.demo02.UserServiceImpl" />
	<bean name="xmlAdvice" class="com.qf.chapter08.demo02.XmlAdvice" />
	<!-- 配置Spring AOP --> 
	<aop:config> 
		<!-- 指定切点 --> 
		<aop:pointcut id="pointcut" expression="execution(* com.qf.chapter08.demo02.UserServiceImpl.*(..))"/> 
		<!-- 指定切面 -->
		<aop:aspect ref="xmlAdvice"> 
			<!-- 指定前置通知 -->
			<aop:before method="before" pointcut-ref="pointcut"/>
			<!-- 指定返回通知 -->
			<aop:after-returning method="afterReturning" pointcut-ref="pointcut"/> 
			<!-- 指定环绕方式 --> 
			<aop:around method="around" pointcut-ref="pointcut" /> 
			<!-- 指定异常通知 --> 
			<aop:after-throwing method="afterException" pointcut-ref="pointcut" /> 
			<!-- 指定后置通知 --> 
			<aop:after method="after" pointcut-ref="pointcut" /> 
		</aop:aspect> 
	</aop:config> 
(6)测试类 TestXml
package com.qf.chapter08.demo02;

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

public class TestXml {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userService = context.getBean("userService", UserService.class);
		userService.delete();
	}
}

2、基于注解开发Spring AOP

(1)创建类 AnnoAdvice.java
package com.qf.chapter08.demo02;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class AnnoAdvice {
	// 切点
	@Pointcut("execution(* com.qf.chapter08.demo02.UserServiceImpl.*(..))")
	public void pointcut() {
	}

	// 前置通知
	@Before("pointcut()")
	public void before() {
		System.out.println("这是前置通知");
	}

	// 后置通知
	@AfterReturning("pointcut()")
	public void afterReturning() {
		System.out.println("这是后置通知(方法不出现异常时调用)");
	}

	// 环绕通知
	@Around("pointcut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		System.out.println("这是环绕通知之前的部分!!");
		// 调用目标方法
		Object object = point.proceed();
		System.out.println("这是环绕通知之后的部分!!");
		return object;
	}

	// 异常通知
	@AfterThrowing("pointcut()")
	public void afterException() {
		System.out.println("异常通知!!");
	}

	// 后置通知
	@After("pointcut()")
	public void after() {
		System.out.println("这是后置通知!!");
	}
}
(2)修改 applicationContext.xml ,beans 标签内容替换为
	<!-- 注册Bean -->
	<bean name="userService" class="com.qf.chapter08.demo02.UserServiceImpl" /> 
	<bean name="annoAdvice" class="com.qf.chapter08.demo02.AnnoAdvice" /> 
	<!-- 开启@aspectj的自动代理支持 -->
	<aop:aspectj-autoproxy />
(4)测试类 TestAnnotation
package com.qf.chapter08.demo02;

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

public class TestAnnotation {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userService = context.getBean("userService", UserService.class);
		userService.insert();
	}
}

三、Spring AOP的应用

1、性能监控

(1)Services01.java
package com.qf.chapter08.demo03;

public class Service01 {
	public void service() throws Exception {
		System.out.println("执行service()方法");
		Thread.sleep(1000);
	}
}
(2)Record.java
package com.qf.chapter08.demo03;

import java.util.Date;

public class Record {
	private String className; // 类名称
	private String methodName; // 方法名称
	private Date recordTime; // 记录时间
	private Long expendTime; // 程序执行耗费的时间

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public Date getRecordTime() {
		return recordTime;
	}

	public void setRecordTime(Date recordTime) {
		this.recordTime = recordTime;
	}

	public Long getExpendTime() {
		return expendTime;
	}

	public void setExpendTime(Long expendTime) {
		this.expendTime = expendTime;
	}

	@Override
	public String toString() {
		return "Record [className=" + className + ", methodName=" + methodName + ", recordTime=" + recordTime
				+ ", expendTime=" + expendTime + "]";
	}
}
(3)RecordAspect.java
package com.qf.chapter08.demo03;

import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class RecordAspect {
	@Pointcut("execution(* com.qf.chapter08.demo03.Service*.*(..))")
	public void record() {
	}

	@Around("record()")
	public Object recordTimer(ProceedingJoinPoint thisJoinPoint) throws Throwable {
		// 获取目标对象的类名称
		String clazzName = thisJoinPoint.getTarget().getClass().getName();
		// 获取目标对象的方法名称
		String methodName = thisJoinPoint.getSignature().getName();
		// 计算目标对象对应方法执行所耗时间
		long startTime = System.currentTimeMillis();
		Object result = thisJoinPoint.proceed();
		long time = System.currentTimeMillis() - startTime;
		Record record = new Record();
		record.setExpendTime(time); // 记录执行所耗时间
		record.setClassName(clazzName); // 记录类名称
		record.setMethodName(methodName); // 记录对应方法名称
		record.setRecordTime(new Date()); // 记录时间
		System.out.println(record.toString());
		return result;
	}
}
(4)applicationContext_record.xml

resources目录下新建chapter08目录,在chapter08目录下新建

<?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">
    
	<bean name="service01" class="com.qf.chapter08.demo03.Service01" />
	<bean name="recordAspect" class="com.qf.chapter08.demo03.RecordAspect" />
	<aop:aspectj-autoproxy />

</beans>
(5)测试类 TestRecord.java
package com.qf.chapter08.demo03;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qf.chapter08.demo03.Service01;

public class TestRecord {
	public static void main(String[] args) throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("chapter08/applicationContext_record.xml");
		Service01 service01 = context.getBean("service01", Service01.class);
		service01.service();
	}
}

2、异常监控

(1)自定义异常类
package com.qf.chapter08.demo03;

public class MyException extends Exception {
	private static final long serialVersionUID = 1L;
	private String msg;

	public MyException(String msg) {
		super();
		this.msg = msg;
	}

	public String getMsg() {
		return msg;
	}
}
(2)Services02.java
package com.qf.chapter08.demo03;

public class Service02 {
	public void service() throws Exception {
		System.out.println("执行service()方法");
		int num = 105;
		if (num > 100 || num < 0) {
			throw new MyException("您输入的不正确,请输入0--100之间的数字");
		} else {
			System.out.println("您输入的数字是" + num);
		}
	}
}
(3)Message.java
package com.qf.chapter08.demo03;

import java.util.Date;

public class Message {
	private String className;
	private String methodName;
	private Date recordTime; // 异常记录时间
	private String exceptionMsg; // 异常信息

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public Date getRecordTime() {
		return recordTime;
	}

	public void setRecordTime(Date recordTime) {
		this.recordTime = recordTime;
	}

	public String getExceptionMsg() {
		return exceptionMsg;
	}

	public void setExceptionMsg(String exceptionMsg) {
		this.exceptionMsg = exceptionMsg;
	}

	@Override
	public String toString() {
		return "Message [className=" + className + ", " + "methodName=" + methodName + ", recordTime=" + recordTime
				+ ", exceptionMsg=" + exceptionMsg + "]";
	}
}
(4)MessageAspect.java
package com.qf.chapter08.demo03;

import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect
public class MessageAspect {
	@Pointcut("execution(* com.qf.chapter08.demo03.Service*.*(..))")
	public void exceptionMsg() {
	}

	@Around("exceptionMsg()")
	public Object msgMethod(ProceedingJoinPoint thisJoinPoint) throws Throwable {
		// 获取目标对象的类名称
		String clazzName = thisJoinPoint.getTarget().getClass().getName();
		// 获取目标对象的方法名称
		String methodName = thisJoinPoint.getSignature().getName();
		try {
			return thisJoinPoint.proceed();
		} catch (MyException e) {
			Message msg = new Message();
			// 封装异常信息
			msg.setClassName(thisJoinPoint.getTarget().getClass().getName());
			msg.setMethodName(thisJoinPoint.getSignature().getName());
			msg.setRecordTime(new Date());
			msg.setExceptionMsg(e.getMsg());
			System.out.println(msg.toString());
			return null;
		}
	}
}
(5)applicationContext_msg.xml

在chapter08目录下新建

<?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">
    
	<bean name="service01" class="com.qf.chapter08.demo03.Service01" />
	<bean name="recordAspect" class="com.qf.chapter08.demo03.RecordAspect" />
	<aop:aspectj-autoproxy />
	<bean name="service02" class="com.qf.chapter08.demo03.Service02"/>
   <bean name="messageAspect"  class="com.qf.chapter08.demo03.MessageAspect"/>
   <aop:aspectj-autoproxy/>
	
</beans>
(5)测试类 TestMessage.java
package com.qf.chapter08.demo03;

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

public class TestMessage {
	public static void main(String[] args) throws Exception {
		ApplicationContext context = new ClassPathXmlApplicationContext("chapter08/applicationContext_msg.xml");
		Service02 service02 = context.getBean("service02", Service02.class);
		service02.service();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值