`

Spring aop 基于schema的AOP支持及JoinPoint的使用、如何使用CGLIB代理

阅读更多

 基于schema的aop只是将配置写到配置文件中。

代码:

package com.lwf.aop;

public interface UserManager {

	public void add(String name, String password);
	public void del(String id);
	public void modify(int id ,String name, String password);
}

 

package com.lwf.aop;

public class UserManagerImpl implements UserManager {

	public void add(String name, String password) {

		System.out.println("add method");
	}

	public void del(String id) {
		System.out.println("del method");
	}

	public void modify(int id, String name, String password) {
		System.out.println("modify method");
	}

}

 

package com.lwf.aop;

public interface MySecurityManager {

	public void checkSecurity();
}

 

package com.lwf.aop;

public class MySecurityManagerImpl implements MySecurityManager {
	public void checkSecurity() {
		System.out.println("User security Check");
	}

}

 

注意上面的实现类中没有做任何@AspectJ的声明。

配置文件:

<?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:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
		
>
	
	<bean id="userManager" class="com.lwf.aop.UserManagerImpl"></bean>
	<bean id="mySecurityManager" class="com.lwf.aop.MySecurityManagerImpl"></bean>
	<aop:config>
		<aop:aspect id="mySecurity" ref="mySecurityManager">
			<aop:pointcut expression="execution(* add*(..)) || execution(* del*(..))" id="allAddMethod" />
			<aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
		</aop:aspect>
	</aop:config>
</beans>

 

测试类:

package com.lwf.aop;

import junit.framework.TestCase;

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

public class Client extends TestCase{

	public void testAop(){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserManager userManager = (UserManager)ac.getBean("userManager");
		userManager.add("zhangshang", "123456");
		userManager.del("23");
	}
}

 结果:

 

User security Check
add method
User security Check
del method

 注意我们配置文件中删除了:<aop:aspectj-autoproxy/>

 

JoinPoint的使用

在上面的checkSecurity方法中,我们没办法得到横切对象方法如add方法的参数。我们使用JoinPoint来解决。

上面示例只需要修改对应的checkSecurity方法即可。如我们修改MySecurityManagerImpl如下:

package com.lwf.aop;

import org.aspectj.lang.JoinPoint;

public class MySecurityManagerImpl implements MySecurityManager {
	public void checkSecurity(JoinPoint joinPoint) {
		 Object args[] = joinPoint.getArgs();
		 if(args!=null){
			for (int i = 0; i < args.length; i++) {
				System.out.println("args[" +i+"] =" + args[i]);
			}
		 }
		System.out.println("User security Check");
	}

}

 

我们通过给checkSecurity方法增加JoinPoint joinPoint参数,再通过getArgs方法得到add方法的参数。

现在测试Client.java

 

package com.lwf.aop;

import junit.framework.TestCase;

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

public class Client extends TestCase{

	public void testAop(){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserManager userManager = (UserManager)ac.getBean("userManager");
		userManager.add("zhangshang", "123456");
		//userManager.del("23");
	}
}

 

输出如下:

args[0] =zhangshang
args[1] =123456
User security Check
add method

 

我们看到获取了用户名和密码。这种方法在不修改配置文件的条件下即可获得add方法参数。

 

需要注意的是因为spring aop默认采用的是J2SE实现的动态代理机制,而动态代理机制只能对接口代理,所以上面的代码UserManager必须是接口。如果不使用接口则要使用cglib代理,因为cglib代理可以对类实现代理

如何使用cglib代理?

我们可以强制让spring aop使用cglib代理而不是jdk的动态代理。

只要在配置文件中将

<aop:config proxy-target-class="true">

 并且增加cglib库到我们的用户自定义库中。

下面来测试:

我们首先删除UserManager接口,也删除MySecurityManager接口(这个接口本来就可以不要)。

修改Client的测试代码。剩下的代码如下所示。

注意我们先不使用cglib测试:

package com.lwf.aop;

public class UserManagerImpl {

	public void add(String name, String password) {

		System.out.println("add method");
	}

	public void del(String id) {
		System.out.println("del method");
	}

	public void modify(int id, String name, String password) {
		System.out.println("modify method");
	}

}

 

package com.lwf.aop;

import org.aspectj.lang.JoinPoint;

public class MySecurityManagerImpl  {
	public void checkSecurity(JoinPoint joinPoint) {
		 Object args[] = joinPoint.getArgs();
		 if(args!=null){
			for (int i = 0; i < args.length; i++) {
				System.out.println("args[" +i+"] =" + args[i]);
			}
		 }
		System.out.println("User security Check");
	}

}

 

package com.lwf.aop;

import junit.framework.TestCase;

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

public class Client extends TestCase{

	public void testAop(){
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		//UserManager userManager = (UserManager)ac.getBean("userManager");
		//userManager.add("zhangshang", "123456");
		//userManager.del("23");
		
		UserManagerImpl userManager = (UserManagerImpl)ac.getBean("userManager");
		userManager.add("zhangshang", "123456");
	}
}

 

<?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:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
		
>
	
	<bean id="userManager" class="com.lwf.aop.UserManagerImpl"></bean>
	<bean id="mySecurityManager" class="com.lwf.aop.MySecurityManagerImpl"></bean>
	<aop:config >
		<aop:aspect id="mySecurity" ref="mySecurityManager">
			<aop:pointcut expression="execution(* add*(..)) || execution(* del*(..))" id="allAddMethod" />
			<aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
		</aop:aspect>
	</aop:config>
</beans>

 测试输出结果:

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'userManager' defined in class path resource [applicationContext.xml]: 
Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: 
Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.	

 我们可以看到删除UserManager接口,而默认情况下使用JDK动态代理又需要该接口,所以报错,提示在这种情况下应该要使用cglib代理。

下面我们使用cglib代理,一加入cglib库,二修改配置文件如下:

<?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:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
		
>
	
	<bean id="userManager" class="com.lwf.aop.UserManagerImpl"></bean>
	<bean id="mySecurityManager" class="com.lwf.aop.MySecurityManagerImpl"></bean>
	<aop:config proxy-target-class="true">
		<aop:aspect id="mySecurity" ref="mySecurityManager">
			<aop:pointcut expression="execution(* add*(..)) || execution(* del*(..))" id="allAddMethod" />
			<aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
		</aop:aspect>
	</aop:config>
</beans>

 

输出结果:

args[0] =zhangshang
args[1] =123456
User security Check
add method

 

通常我们使用JDK的动态代理就可以了,一般我们是对一些之前开发的系统,因为没有接口类,所以考虑使用cglib代理进行增加spring aop 的功能。

J2SE动态代理和CGLIB字节码生成代理的区别?
	* J2SE动态代理只针对接口进行代理,不能针对类
	* CGLIB是针对类实现代理,主要对指定的类生成一个子类,并覆盖其中的方法,从而实现方法的拦截,
	  因为是通过继承,所以无法为final方法提供代理

 

分享到:
评论

相关推荐

    spring之AOP(动态代理)

    然而,如果需要更精细的控制,可以通过`@EnableAspectJAutoProxy`注解开启基于AspectJ的自动代理支持,或者通过`proxyTargetClass`属性来强制使用CGLIB代理。 总结一下,Spring的AOP机制通过JDK动态代理和CGLIB动态...

    Spring AOP之基于Schema配置总结与案例

    **Spring AOP:基于Schema配置的总结与案例** 在Java企业级开发中,Spring框架以其强大的功能和灵活性深受开发者喜爱。其中,Spring AOP(面向切面编程)是解决横切关注点问题的一个重要工具,它允许我们把业务逻辑...

    征服Spring AOP—— Schema

    对于工具的使用,Spring提供的`spring-instrument`模块可以用于类加载时的增强,以便于AOP代理的创建。 总结来说,Spring AOP的Schema配置是实现面向切面编程的一种方式,它通过XML定义切面、切入点和通知,使得非...

    基于注解实现SpringAop

    基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)

    基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)...

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    在 Spring AOP 中,`ObjenesisCglibAopProxy` 类负责使用 CGLIB 创建代理对象,它会将一系列的 `MethodInterceptor` 注册为 `Callback`,这些 `MethodInterceptor` 执行了 AOP 的逻辑。 在 Spring AOP 的自动代理...

    springAop.rar_AOP java_cglib_spring aop

    在Spring AOP中,有两种主要的实现方式:代理模式和CGLIB。代理模式是基于接口的,当目标对象实现了接口时,Spring会创建一个与该接口匹配的代理对象,通过代理对象来执行增强的逻辑。而CGLIB(Code Generation ...

    Spring AOP 16道面试题及答案.docx

    Spring支持两种AOP的实现方式:Spring AspectJ注解风格和Spring XML配置风格。使用AspectJ注解风格是最常见的,它允许开发者直接在方法上使用注解来定义切面。 Spring AOP中有五种不同类型的的通知(Advice): 1....

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,Spring AOP会采用CGLIB来生成代理对象。CGLIB(Code Generation Library)是一个开源的代码生成库,它允许运行时在内存中...

    spring aop jar 包

    Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。这个"spring aop jar 包"包含了实现这一功能所需的类和接口,...

    spring_aop_cglib的实现方式

    在Spring配置中,如果我们希望使用CGLIB代理,可以在`&lt;aop:config&gt;`或`&lt;aop:aspectj-autoproxy&gt;`元素下添加`&lt;aop:proxy&gt;`子元素,并设置`proxy-target-class="true"`。例如: ```xml &lt;aop:config&gt; &lt;aop:aspect id=...

    简单spring aop 例子

    1. **代理**:Spring AOP支持两种类型的代理:JDK动态代理和CGLIB代理。JDK代理用于实现了接口的类,而CGLIB代理则用于没有接口或不希望使用接口的类。代理对象在调用目标方法时会执行切面逻辑。 2. **织入**:织入...

    springAop默认代理方式.zip

    2. **动态代理**:Spring AOP 的默认代理方式是动态代理,它包括JDK动态代理和CGLIB代理。当目标对象实现了至少一个接口时,Spring将使用JDK的动态代理机制。JDK动态代理通过实现InvocationHandler接口,并在运行时...

    Spring Aop使用实例

    Spring AOP有两种实现方式:基于代理的AOP(JDK动态代理和CGLIB代理)和基于注解的AOP。 - **JDK动态代理**:当目标类实现了接口时,Spring会使用JDK的Proxy类创建一个代理对象,该代理对象会在调用接口方法时插入...

    Spring Aop四个依赖的Jar包

    总的来说,Spring AOP通过这四个关键的Jar包,结合AspectJ的强大功能和CGLIB的代理机制,为开发者提供了强大的面向切面编程支持,使得我们可以在不侵入原有业务代码的情况下,实现跨切面的关注点管理。

    Spring AOP面向方面编程原理:AOP概念

    4. **丰富的切入点表达式语言**:Spring AOP支持使用SpEL(Spring Expression Language)来定义复杂的切入点表达式,这让开发者能够更加灵活地控制通知的触发条件。 #### 四、Spring AOP的实现示例 接下来,我们...

    Spring-AOP-JDK动态代理

    5. **配置代理**:Spring会根据目标对象是否实现了接口来决定使用JDK动态代理还是CGLIB代理。如果目标对象实现了接口,Spring会选择JDK动态代理。动态代理类会继承自`java.lang.reflect.Proxy`,并实现目标对象的...

    springAOP配置动态代理实现

    2. **CGLIB动态代理**:如果目标类没有实现接口,Spring会使用CGLIB库创建一个目标类的子类,子类覆盖目标类的方法并在方法调用前后插入通知。CGLIB代理提供了更广泛的应用场景,但相比JDK动态代理,它的性能稍差。 ...

    Spring Aop Schema实现

    本篇文章将深入探讨Spring AOP的Schema实现,即基于XML配置的方式来理解和应用AOP。 一、Spring AOP基础概念 1. 切面(Aspect):切面是关注点的模块化,例如日志、事务管理。在Spring AOP中,切面由通知(Advice...

Global site tag (gtag.js) - Google Analytics