Spring-AOP
导包:
这个是使用spring所需要的必须jar包的关联依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.22.RELEASE</version> </dependency> 这是使用springAOP是要依赖的外部aspectj <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency>
使用xml方式实现动态代理
实例1:
代理对象为CGLIB ,既是没有接口的目标类实现代理
目标类 没有接口 public class Hello { public void sayHello(String word){ System.out.println(word); } } 通知类 方式1使用的 public class MyAOP implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("目标方法调用之前,要开始用"); } } 通知类 方式2使用的 public class MyAOP { public void before(JoinPoint joinPoint){ System.out.println("这里是前置通知,请放心使用"); System.out.println(joinPoint.getThis().getClass()); System.out.println(joinPoint.getArgs()); } public void around(){ } public void after(){ System.out.println("方法执行结束啦"); } }
application.xml配置
通知类: 两种方式: <aop:config> <aop:pointcut expression="execution(* chencj.cc.aop.Hello.*(..))" id="helloT"/> 方式1:直接使用确定的通知类接口的实现类 MethodBeforeAdvice AfterReturningAdvice等等 <aop:advisor advice-ref="myAOP" pointcut-ref="helloT"/> 方式2 通过<aop:aspect ref="myAOP"> 去实现,两者二选一 <aop:aspect ref="myAOP"> <!--;!– before | after | after-returning | after-throwing | around –--> <aop:before method="before" pointcut-ref="helloT"/> <aop:after method="after" pointcut-ref="helloT"/> </aop:aspect </aop:config> 目标类 <bean class="chencj.cc.aop.Hello" id="hello"></bean> 通知类 <bean class="chencj.cc.aop.MyAOP" id="myAOP"></bean>
测试
public class Client { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml"); Hello bean = applicationContext.getBean(Hello.class);//实体类的代理 System.out.println(bean.getClass()); //打印的代理对象是:$EnhancerBySpringCGLIB$$cfffcf3c bean.sayHello("这个世界很大"); } } 结果: class chencj.cc.aop.Hello$$EnhancerBySpringCGLIB$$cfffcf3c 这里是前置通知,请放心使用 class chencj.cc.aop.Hello$$EnhancerBySpringCGLIB$$cfffcf3c [Ljava.lang.Object;@4b14c583 这个世界很大 方法执行结束啦
实例2
代理对象是jdkproxy,对接口的实现
接口类,目标类 public interface IHello{ public void sayHello(String word); } 实体类实现接口 public class Hello implements IHello{ public void sayHello(String word){ System.out.println(word); } } 通知类 就使用 方式1 使用的 public class MyAOP implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("目标方法调用之前,要开始用"); } }
application.xml配置
通知类: <aop:config> <aop:pointcut expression="execution(* chencj.cc.aop.Hello.*(..))" id="helloT"/> 方式1:直接使用确定的通知类接口的实现类 MethodBeforeAdvice AfterReturningAdvice等等 <aop:advisor advice-ref="myAOP" pointcut-ref="helloT"/> </aop:config> 目标接口的实现类,引入接口到spring容器中 <bean class="chencj.cc.aop.Hello" id="hello"></bean> 通知类 <bean class="chencj.cc.aop.MyAOP" id="myAOP"></bean>
测试
public class Client { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml"); IHello bean =applicationContext.getBean(IHello.class);//这里是从spring容器中拿出接口实例化对象, System.out.println(bean.getClass()); //class com.sun.proxy.$Proxy2 bean.sayHello("世界你好啊"); } } 结果是: class com.sun.proxy.$Proxy2 这里是前置通知,请放心使用 世界你好啊
SpringAOP的注解方式实现
application.xml
<!-- 使用注解自动生成代理对象 --> <aop:aspectj-autoproxy/>
通知类上的修改
@Aspect//加入这个切面注解 对应xml中 <aop:aspect> </aop:aspect> public class MyAOP { //只有加入@Aspect,才能使得作用在方法上的注解@Before,@After对应xml中<aop:before/> <aop:after> //生效,"execution(* chencj.cc.aop.Hello.*(..))"----》对应xml中的<aop:pointcut/> @Before("execution(* chencj.cc.aop.Hello.*(..))") public void before(JoinPoint joinPoint){ System.out.println("这里是前置通知,请放心使用"); System.out.println(joinPoint.getThis().getClass()); System.out.println(joinPoint.getArgs()); } public void around(){ } @After("execution(* chencj.cc.aop.Hello.*(..))") public void after(){ System.out.println("方法执行结束啦"); } }
测试
public class Client { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application.xml"); Hello bean = applicationContext.getBean(Hello.class); System.out.println(bean.getClass()); bean.sayHello("这个世界很大"); } } 结果: class chencj.cc.aop.Hello$$EnhancerBySpringCGLIB$$fe63c014 这里是前置通知,请放心使用 class chencj.cc.aop.Hello$$EnhancerBySpringCGLIB$$fe63c014 [Ljava.lang.Object;@49b0b76 这个世界很大 方法执行结束啦
总结:注解方式的aop,比xml书写起来要简单,xml看着比较一目了然