2009.01.29 / 标签:
Spring,
Spring AOP / 分类:
J2EE技术
昨天是使用Annotation注解的方式实现的AOP,今天再将其改为使用配置文件来实现。使用这种方法的话,SecurityHandler类就又少了一大截的代码,只需要提供一个用于标识切点的方法即可。
package cn.ineeke.spring;
public class SecurityHandler {
private void printSomthing(){
System.out.println("--------Security----------");
}
}
虽说类中是不需要使用注解了,但是这个东西肯定是得有的,只不过是将其转移到applicationContext.xml文件中了而已。使用标签配置好DAO类和SecurityHandler类。
使用标签开始配置AOP。标签用于指定哪个bean是切面。标签用于指定切点。标签在这里用于定义Advice,同前面所说的一样,这里还可以是等等。
<?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"
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">
<bean id="securityHandler" class="cn.ineeke.spring.SecurityHandler"/>
<bean id="userDAO" class="cn.ineeke.spring.UserDAOImpl"/>
<aop:config>
<aop:aspect id="securityAspect" ref="securityHandler">
<aop:pointcut id="addMethod" expression="execution(* *(..))"/>
<aop:before method="printSomthing" pointcut-ref="addMethod"/>
</aop:aspect>
</aop:config>
</beans>
调用方法同之前的一样,这样看起来应该比昨天那个清晰的多了,看标签也比较好容易理解。
2009.01.28 / 标签:
Spring,
Spring AOP / 分类:
J2EE技术
使用Annotation方式重新实现昨天的例子。重新修改SecurityHandler类,使用@Aspect声明此类为一个使用了AOP技术的切面。提供一个方法allMethod(),该方法无参且无返回类型也没有具体的代码实现,用于定义Pointcut(切入点)。Pointcut的内容是一个表达式,用于描述对哪些方法进行切入(类似于拦截的作用)。
定义Advice,字面上是“建议”的意思,这里可以理解为所要向切入点中插入的其他操作。@Before表示该Advice是在切入点中方法执行之前被执行,其参数是指在哪个Pointcut中织入该Advice。除了Before当然还有其它的了,可以百度一下。
该SecurityHandler类的完整代码如下:
package cn.ineeke.spring;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class SecurityHandler {
@Pointcut("execution(* *(..))")
private void allMethod(){
}
@Before("allMethod()")
private void printSomthing(){
System.out.println("--------Security----------");
}
}
在execution(* *(..))中,其格式为execution(返回类型 方法名(参数)),“*”和“..”均表示所有。
接下来需要启用Aspectj对Annotation的支持,并将Aspect类和目标对象配置到IOC容器中。修改applicationContext.xml文件,使用标签启用支持。使用标签进行相关配置。
完整配置如下:
<?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"
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">
<aop:aspectj-autoproxy/>
<bean id="securityHandler" class="cn.ineeke.spring.SecurityHandler"/>
<bean id="userDAO" class="cn.ineeke.spring.UserDAOImpl"/>
</beans>
最后再写个测试类测试一下。
package cn.ineeke.spring;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
public static void main(String[] args) {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserDAO userDAO = (IUserDAO) factory.getBean("userDAO");
userDAO.getUser();
}
}
最后需要注意的是,这里用于定义Pointcut的allMethod()方法并不会被执行,它仅仅只是起到一个标识的作用。不信的话可以在allMethod()方法中写点什么,运行一下看看是否会被执行。
2009.01.27 / 标签:
Spring,
Spring AOP / 分类:
J2EE技术
在没有使用Spring之前,如果要对DAO层进行修改,比如说做数据安全性验证。那么,就需要对DAO层中的每一个方法都进行修改,项目小了好说,大了的话呢?不久后又要删掉这一功能呢?那岂不又是费神之事。
这一问题使用AOP(Aspect Oriented Programming 面向切面编程)就好解决的多了。面向切面编程,就像使用FilterServlet(过滤器)对字符编码进行转换时一样。当BIZ层调用DAO层中的方法时,可以对其实施拦截,在前之前或之后插入所要执行的操作。
下面看看具体如何对这一问题进行应用。首先创建一个安全性检测类SecurityHandler并让它实现InvocationHandler接口。声明一个Object类型的变量用于存储目标对象(我们要对谁进行拦截)。提供一个方法getProxy(),该方法接收目标对象然后返回该对象的代理对象。在invoke()方法中先进行数据安全性检测,然后再调用目标对象的方法。因为无法确定所调用的方法是或否有返回值,所以默认的令其返回Object类型。完整代码如下:
package cn.ineeke.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SecurityHandler implements InvocationHandler {
//用于存储目标对象
private Object obj;
//获得目标对象的代理
public Object getProxy(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
//方法调用
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
printSomthing();
Object ret = null;
try {
ret = method.invoke(this.obj, args);
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
private void printSomthing(){
System.out.println("--------Security----------");
}
}
接下来编写一个测试类。
package cn.ineeke.spring;
public class Client {
public static void main(String[] args) {
SecurityHandler sryHandler = new SecurityHandler();
IUserDAO userDAO = (IUserDAO) sryHandler.getProxy(new UserDAOImpl());
userDAO.getUser();
}
}
上面的代码中,首先创建了一个SecurityHandler的实例sryHandler,然后调用getProxy()方法根据具体的目标对象创建具体的代理对象,最后通过代理来调用相关的方法。这么一来,无论是开发阶段还是后期的维护中,如果需要改动,则只需要改动SecurityHandler类即可,不再需要对DAO中每个方法逐一改动了。