spring的代理以及aop

spring整合junit测试:
1.导包aop+test
2.@RunWith(SpringJUnit4ClassRunner.class)//帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml")//指定创建容器时使用那个配置文件
public class Demo2 {
@Resource(name="user")//将名为user的对象注入到u变量中
private User u;
@Test
public void fun1(){
	System.out.println(u);
}
}

spring实现的aop的原理:
UserService接口:
public interface UserService {
void save();
void delete();
void update();
void find();
}
UserServiceImple实现类:
public class UserServiceImpl implements UserService{
public void save(){
	System.out.println("保存用户");
}
public void delete(){
	System.out.println("删除用户");
}
public void find(){
	System.out.println("查找用户");
}
public void update(){
	System.out.println("更新用户");
}
}

1.动态代理:(优先)
	被代理的对象必须要实现接口,才能产生代理对象,如果没有接口将不能用动态代理技术
UserServiceProxyFactory代理工厂:
public class UserServiceProxyFactory implements InvocationHandler{
	public UserServiceProxyFactory(UserService us){
		this.us=us;
	}
	private UserService us;
	public UserService  getUserServiceProxy(){
		//生成动态代理
		UserService usProxy=(UserService)Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), this);
		return usProxy;
	}

	@Override
	public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
		System.out.println("打开事务");;
		Object invoke=method.invoke(us,arg2);
		System.out.println("提交事务");
		return null;
	}
}

测试类:
@Test
public void fun1(){
	UserService us=new UserServiceImpl();
	UserServiceProxyFactory factory=new UserServiceProxyFactory(us);
	UserService usPorxy=factory.getUserServiceProxy();
	usPorxy.save();
}

2.cglib代理:
	第三方代理技术,cglib代理,可以对任何类型生成代理,代理的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理
UserServiceProxyFactory2工厂类:
public class UserServiceProxyFactory2 implements MethodInterceptor{
	public UserService getUserServiceProxy(){
		Enhancer en=new Enhancer();//帮我们生成代理对象
		en.setSuperclass(UserServiceImpl.class);//设置对谁进行代理
		en.setCallback(this);//代理要做什么
		UserService us=(UserService)en.create();//创建代理对象
		return us;
	}

	@Override
	public Object intercept(Object proxyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
		//打开事务
		System.out.println("打开事务");
		//调用原有方法
		Object returnValue=methodProxy.invokeSuper(proxyobj, arg);
		//提交事务
		System.out.println("提交事务");
		return returnValue;
	}
}

测试方法:
@Test
public void fun2(){ 
	UserServiceProxyFactory2 factory=new UserServiceProxyFactory2();
	UserService usPorxy=factory.getUserServiceProxy();
	usPorxy.save();
	//代理对象继承了被代理对象
	System.out.println(usPorxy instanceof UserServiceImpl);//判断代理对象是否属于被代理对象类型
}

spring的aop:
通知类:MyAdvice:
public class MyAdvice {
	//前置通知->目标方法之前调用
	//后置通知(如果出现异常不会调用)->在目标方法运行之后调用
	//环绕通知->在目标方法之前和之后都调用
	//异常拦截通知->如果出现异常就会调用
	//后置通知(无论出现异常都会调用)
	public void before(){
		System.out.println("这是前置通知");
	}
	public void afterRunning(){
		System.out.println("这是后置通知,如果出现异常不会调用");
	}
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
	System.out.println("在环绕通知之前的部分");
	Object proceed=pjp.proceed();//调用目标方法
	System.out.println("在环绕通知之后的部分");
	return proceed;
	}
	public void afterException(){
		System.out.println("出事啦出现异常了");
	}
	public void after(){
		System.out.println("这是后置通知");
	}
}

配置文件applicationContext.xml(注意:约束不一样)
<?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: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.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 准备工作: 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
	<bean name="userService" class="cn.itcast.service.UserServiceImpl" ></bean>
<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="cn.itcast.d_aop.MyAdvice" ></bean>
<!-- 3.配置将通知织入目标对象 -->
	<aop:config>
		<!-- 配置切入点 
			public void cn.itcast.service.UserServiceImpl.save() 
			void cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.save()
			* cn.itcast.service.UserServiceImpl.*()
			
			* cn.itcast.service.*ServiceImpl.*(..)
			* cn.itcast.service..*ServiceImpl.*(..)
		-->
		<aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/>
		<aop:aspect ref="myAdvice" >
			<!-- 指定名为before方法作为前置通知 -->
			<aop:before method="before" pointcut-ref="pc" />
			<!-- 后置 -->
			<aop:after-returning method="afterRunning" pointcut-ref="pc" />
			<!-- 环绕通知 -->
			<aop:around method="around" pointcut-ref="pc" />
			<!-- 异常拦截通知 -->
			<aop:after-throwing method="afterException" pointcut-ref="pc"/>
			<!-- 后置 -->
			<aop:after method="after" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config>
</beans>
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/cn/itcast/d_aop/applicationContext.xml")
public class Demo {
	@Resource(name="userService")
	private UserService us;
	@Test
	public void fun1(){
		us.save();
	}
}
spring的aop注解配置:
applicationContext.xml配置文件
<?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: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.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

<!-- 准备工作: 导入aop(约束)命名空间 -->
<!-- 1.配置目标对象 -->
	<bean name="userService" class="cn.itcast.service.UserServiceImpl" ></bean>
<!-- 2.配置通知对象 -->
	<bean name="myAdvice" class="cn.itcast.e_annotation.MyAdvice" ></bean>
<!-- 3.开启使用注解完成植入 -->
	 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
@Aspect//表示该类是一个通知类
public class MyAdvice {
	//前置通知->目标方法之前调用
	//后置通知(如果出现异常不会调用)->在目标方法运行之后调用
	//环绕通知->在目标方法之前和之后都调用
	//异常拦截通知->如果出现异常就会调用
	//后置通知(无论出现异常都会调用)
	//指定该方法是前置通知并制定切入点
	@Pointcut("execution(* cn.itcast.service.*ServiceImpl.*(..))")
	public void pc(){
		
	}
	@Before("MyAdvice.pc()")
	public void before(){
		System.out.println("这是前置通知");
	}
	@AfterReturning("execution(* cn.itcast.service.*ServiceImpl.*(..))")
	public void afterRunning(){
		System.out.println("这是后置通知,如果出现异常不会调用");
	}
	@Around("execution(* cn.itcast.service.*ServiceImpl.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
	System.out.println("在环绕通知之前的部分");
	Object proceed=pjp.proceed();//调用目标方法
	System.out.println("在环绕通知之后的部分");
	return proceed;
	}
	@AfterThrowing("execution(* cn.itcast.service.*ServiceImpl.*(..))")
	public void afterException(){
		System.out.println("出事啦出现异常了");
	}
	@After("execution(* cn.itcast.service.*ServiceImpl.*(..))")
	public void after(){
		System.out.println("这是后置通知");
	}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:cn/itcast/e_annotation/applicationContext.xml")
public class Demo {
@Resource(name="userService")
private UserService us;
@Test
public void fun1(){
	us.save();
}
}





猜你喜欢

转载自blog.csdn.net/qq_36594703/article/details/78984786