基于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方法提供代理