@AspectJ注解驱动,基于xml文件的配置方式

版权声明:仅供学习交流使用 https://blog.csdn.net/drxRose/article/details/84801522

基于xml文件的配置方式,使用@AspectJ注解驱动.需要引入额外的jar包,即aspectj,从官网下载即可.

aop:scoped-proxy 代理的作用域
aop:aspectj-autoproxy 开启@AspectJ注解驱动
aop:config 定义一个spring aop
aop:advisor 定义一个通知器
aop:aspect 定义一个切面
aop:before 定义前置通知
aop:after 定义后置通知
aop:around 定义环绕通知
aop:after-returning 定义返回通知
aop:after-throwing 定义异常通知
aop:declare-parents 对目标对象引入新特性
aop:pointcut 定义一个可复用的切点

目标对象的接口和类

package siye;
public interface User
{
	void work();// 用户工作
}
package siye;

public class UserImpl implements User {

	@Override
	public void work() {
		System.out.println("user_work");
	}

	public int getSalary() {
		return 0;
	}

	public void goHome() {
		System.out.println("user_go_home");
	}

	public void throwOwn() {
		throw new RuntimeException();
	}

}

对目标对象新增特性的接口和类

package siye;
public interface Animal
{
	void eat();
}
package siye;
public class AnimalImpl implements Animal
{
	@Override
	public void eat()
	{
		System.out.println("animal_eat_food");
	}
}

定义的切面类

package siye;
import org.aspectj.lang.ProceedingJoinPoint;
public class CustomAspect
{
	public void before()
	{
		System.out.println("方法即将执行----advice_before");
	}
	public void after()
	{
		System.out.println("方法执行完毕----advice_after");
	}
	public void afterReturning()
	{
		System.out.println("方法正常返回---advice_afterReturning");
	}
	public void aroundMethod(ProceedingJoinPoint jp)
	{
		try
		{
			System.out.println("user_start_back_home");
			jp.proceed();
			System.out.println("user_back_home");
		} catch (Throwable e)
		{
		}
	}
	public void throwException()
	{
		System.out.println("方法抛出异常----advice_throwException");
	}
}

xml配置文件设定,文件名`config.xml`

<bean id="userImpl" class="siye.UserImpl" />                                    
<bean id="aspect" class="siye.CustomAspect" />                                  
                                                                                
                                                                                
<!--强制使用cglib代理. -->                                                            
<aop:config proxy-target-class="true">                                          
	<aop:aspect ref="aspect">                                                   
		<!--定义切点. -->                                                           
		<aop:pointcut                                                           
			expression="execution(* *.UserImpl.work(..))" id="funWork" />       
		<!--前置通知. -->                                                           
		<aop:before method="before" pointcut-ref="funWork" />                   
		<!--后置通知. -->                                                           
		<aop:after method="after" pointcut-ref="funWork" />                     
		<!--环绕通知. -->                                                           
		<aop:after-returning method="afterReturning"                            
			pointcut="execution(* *.getSalary(..))" />                          
		<!--返回通知. -->                                                           
		<aop:around method="aroundMethod"                                       
			pointcut="execution(* *.goHome(..))" />                             
		<!--异常通知. -->                                                           
		<aop:after-throwing method="throwException"                             
			pointcut="execution(* *.throwOwn(..))" />                           
		<!--introduction_by_xml -->                                             
		<aop:declare-parents types-matching="siye.User+"                        
			implement-interface="siye.Animal" default-impl="siye.AnimalImpl" /> 
	</aop:aspect>                                                               
</aop:config>                                                                   

测试类

package siye;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UintTest
{
	public static void main(String[] args)
	{
		ClassPathXmlApplicationContext context =
				new ClassPathXmlApplicationContext();
		context.setConfigLocation("classpath:/siye/config.xml");
		context.refresh();
		/*
		 * 以下三种获取bean的方式,都会报错异常.
		 * 因spring aop配置的不是强制使用cglib动态代理.
		 * 
		 * 设置属性proxy-target-class="true"
		 * 这将强制spring aop使用cglib动态代理.
		 * 
		 * 注解S2,EnableAspectJAutoProxy中,设置
		 * boolean proxyTargetClass() default false;
		 * 此属性为true即可.
		 */
		// NoSuchBeanDefinitionException: No qualifying bean of type
		// 'std_aop_byxml.UserImpl' available
		// UserImpl userImpl = context.getBean(UserImpl.class);

		// BeanNotOfRequiredTypeException: Bean named 'userImpl' is expected to be of
		// type 'std_aop_byxml.UserImpl' but was actually of type
		// 'com.sun.proxy.$Proxy2'
		// UserImpl userImpl = context.getBean("userImpl", UserImpl.class);

		// ClassCastException: com.sun.proxy.$Proxy2 cannot be cast to
		// std_aop_byxml.UserImpl
		// UserImpl userImpl = (UserImpl) context.getBean("userImpl");
		// userImpl.work();

		UserImpl userImpl = context.getBean(UserImpl.class);
		// userImpl.work(); // 测试前置和后置通知.
		// userImpl.getSalary();// 测试返回通知
		// userImpl.goHome();// 测试环绕通知.
		// userImpl.throwOwn();// 测试异常通知.
		/*
		 * 为目标接口的子类,引入新的特性.
		 */
		Animal animal = (Animal) userImpl;
		animal.eat();
		context.close();
	}
}

猜你喜欢

转载自blog.csdn.net/drxRose/article/details/84801522