spring--AOP

AOP实现原理—动态代理&CGLib代理

下面以事务管理为例,手动实现动态代理和cglib代理。对于增删改查方法,都需要开启事务,再进行操作,最后关闭事务。动态代理或者cglib代理就可以把这些事务管理的公共代码进行抽取,不必在增删改查方法里都写上事务管理的代码了,通过代理对象调用增删改查方法的时候会自动加上事务管理的代码。

动态代理

只能为接口创建动态代理对象

在这里插入图片描述
UserService.java

package cn.ccnuacmhdu.service;

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

UserServiceImp.java

package cn.ccnuacmhdu.service;

public class UserServiceImp implements UserService {

	public void add() {
		System.out.println("增加用户");
	}

	public void delete() {
		System.out.println("删除用户");
	}

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

	public void find() {
		System.out.println("查找用户");
	}

}

UserServiceProxyFactory.java

package cn.ccnuacmhdu.proxy;

import java.lang.reflect.Proxy;

import cn.ccnuacmhdu.service.UserService;

public class UserServiceProxyFactory {
	public static UserService getUserServiceProxy(UserService userService) {
		MyInvocationHandler handler = new MyInvocationHandler();
		handler.setUserService(userService);
		
		return (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), 
				userService.getClass().getInterfaces(), handler);
	}
}

MyInvocationHandler.java

package cn.ccnuacmhdu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import cn.ccnuacmhdu.service.UserService;

public class MyInvocationHandler implements InvocationHandler{

	private UserService userService;//被代理接口的对象(面向抽象编程,传入对象赋给UserService)
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		System.out.println("打开事务");
		
		Object result = method.invoke(userService, args);
		
		System.out.println("关闭事务");
		return result;
	}
	
}

Demo.java

package cn.ccnuacmhdu.demo;

import org.junit.Test;

import cn.ccnuacmhdu.proxy.UserServiceProxyFactory;
import cn.ccnuacmhdu.service.UserService;
import cn.ccnuacmhdu.service.UserServiceImp;

public class Demo {
	@Test
	public void fun() {
		UserService userService = new UserServiceImp();
		UserService userServiceProxy = UserServiceProxyFactory.getUserServiceProxy(userService);
		userServiceProxy.add();
	}
}

在这里插入图片描述

cglib代理

可以对任何类生成代理,原理是对目标对象进行**继承代理**

cglib代理的实现已经被整合到了spring核心包中,需要导入spring核心包。

在这里插入图片描述

UserServiceImp.java

package cn.ccnuacmhdu.service;

public class UserServiceImp implements UserService {

	public void add() {
		System.out.println("增加用户");
	}

	public void delete() {
		System.out.println("删除用户");
	}

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

	public void find() {
		System.out.println("查找用户");
	}

}

MyMethodInterceptor.java

package cn.ccnuacmhdu.proxy;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class MyMethodInterceptor implements MethodInterceptor{

	//obj:被代理对象,method:被代理对象的方法,arg方法参数,methodProxy:方法的代理
	public Object intercept(Object obj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
		
		System.out.println("打开事务");
		
		Object result = methodProxy.invokeSuper(obj, arg);
		
		System.out.println("关闭事务");
		
		return result;
	}
	
}

UserServiceProxyFactory.java

package cn.ccnuacmhdu.proxy;

import org.springframework.cglib.proxy.Enhancer;

import cn.ccnuacmhdu.service.UserService;
import cn.ccnuacmhdu.service.UserServiceImp;

public class UserServiceProxyFactory {
	public static UserService getUserServiceProxy() {
	
		Enhancer enhancer = new Enhancer();//enhancer负责生成某个对象的代理
		enhancer.setSuperclass(UserServiceImp.class);//打入要被代理的对象
		enhancer.setCallback(new MyMethodInterceptor());
		UserService userServiceImpProxy = (UserService) enhancer.create();//创建代理对象
		return userServiceImpProxy;
	}
}

Demo.java

package cn.ccnuacmhdu.demo;

import org.junit.Test;

import cn.ccnuacmhdu.proxy.UserServiceProxyFactory;
import cn.ccnuacmhdu.service.UserService;
import cn.ccnuacmhdu.service.UserServiceImp;

public class Demo {
	@Test
	public void fun() {
		UserService userService = new UserServiceImp();
		UserService userServiceProxy = UserServiceProxyFactory.getUserServiceProxy();
		userServiceProxy.add();
	}
}

在这里插入图片描述

AOP相关名词

在这里插入图片描述

spring的AOP配置

(1)导包

spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
在这里插入图片描述
\spring-framework-3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0
在这里插入图片描述
spring-framework-4.2.4.RELEASE-dist\spring-framework-4.2.4.RELEASE\libs
在这里插入图片描述
在这里插入图片描述

再加上spring核心包及日志包,所有包如下:
在这里插入图片描述

(2)准备目标对象

package cn.ccnuacmhdu.service;

public class UserServiceImp implements UserService {

	public void add() {
		System.out.println("增加用户");
	}

	public void delete() {
		System.out.println("删除用户");
	}

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

	public void find() {
		System.out.println("查找用户");
	}

}

(3)准备通知

package cn.ccnuacmhdu.springAOP;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
	//前置通知:目标方法运行前调用
	//后置通知:在目标方法运行之后调用(如果出现异常不会调用)
	//环绕通知:在目标方法之前和之后都调用
	//异常拦截通知:出现异常会调用
	//后置通知:在目标方法运行后调用(无论有异常都调用)
	
	public void before() {
		System.out.println("前置通知:目标方法运行前调用");
	}
	public void afterReturing() {
		System.out.println("后置通知:在目标方法运行之后调用(如果出现异常不会调用)");
	}
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("环绕通知:前部分");
		Object proceed = pjp.proceed();
		System.out.println("环绕通知:后部分");
		return proceed;
	}
	public void afterThrowing() {
		System.out.println("异常拦截通知:出现异常会调用");
	}
	public void after() {
		System.out.println("后置通知:在目标方法运行后调用(无论有异常都调用)");
	}
}

(4)织入

1.先导入beans的名字空间xsi。(之前已经导入了beans约束,这里就不导入了)
2.再导入aop约束及名字空间xsi。

在这里插入图片描述
在这里插入图片描述
3.书写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

	<!-- 1.配置目标对象 -->
	<bean name="UserServiceImp" class="cn.ccnuacmhdu.service.UserServiceImp"></bean>
	<!-- 2.配置通知对象 -->
	<bean name="MyAdvice" class="cn.ccnuacmhdu.springAOP.MyAdvice"></bean>
	<!-- 3.将通知织入目标对象 -->
	<aop:config>
		<!-- 配置切入点
			id:起个名字,随便起名,expression:将成为切入点的方法
			public void cn.ccnuacmhdu.service.UserServiceImp.add()
			void cn.ccnuacmhdu.service.UserServiceImp.add()//public可省略
			* cn.ccnuacmhdu.service.UserServiceImp.add()//返回值任意,注意*之后要有空格
			* cn.ccnuacmhdu.service.UserServiceImp.*()//UserServiceImp下的所有方法进行增强,空参方法
			* cn.ccnuacmhdu.service.UserServiceImp.*(。。)//UserServiceImp下的所有方法进行增强,参数任意
			* cn.ccnuacmhdu.service.*ServiceImp.*(..)//service包下以UserServiceImp结尾的所有类下的所有方法进行增强,参数任意
			* cn.ccnuacmhdu.service。.*UserServiceImp.*(。。)//service包下及其所有子包下以UserServiceImp结尾的所有类下的所有方法进行增强,参数任意
		 -->
		<aop:pointcut expression="execution(* cn.ccnuacmhdu.service.*ServiceImp.*(..))" id="pointcut"/>
		<aop:aspect ref="MyAdvice">
			<aop:before method="before" pointcut-ref="pointcut"/>
			<aop:after-returning method="afterReturing" pointcut-ref="pointcut"/>
			<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/>
			<aop:around method="around" pointcut-ref="pointcut"/>
			<aop:after method="after" pointcut-ref="pointcut"/>
		</aop:aspect>
	
	</aop:config>

</beans>

(5)测试

package cn.ccnuacmhdu.demo;

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

import cn.ccnuacmhdu.service.UserService;


public class Demo {
	@Test
	public void fun() {
		ApplicationContext ac = new ClassPathXmlApplicationContext("cn/ccnuacmhdu/springAOP/applicationContext.xml");
		UserService userService = (UserService)ac.getBean("UserServiceImp");
		userService.add();
	}
}

在这里插入图片描述

附:工程架构

在这里插入图片描述

工程源码

点击下载工程源码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值