使用代理为业务操作添加安全检测

 

1.使用静态代理为系统操作添加安全性检查

实例结构图

业务接口定义

package com.dennist.dao;
public interface UserDao {
    
    public void addUser(String name, String password);
    
    public void deleteUser(int id);
    
    public void updateUser(int id, String name, String password);
    
    public String queryUser(int id);

}

接口的实现

package com.dennist.dao.impl;
import com.dennist.dao.UserDao;

public class UserDaoImpl implements UserDao{
    
    @Override
    public void addUser(String name, String password) {
        System.out.println("UserDaoImpl.addUser()");
    }

    @Override
    public void deleteUser(int id) {
        System.out.println("UserDaoImpl.deleteUser()");
    }

    @Override
    public String queryUser(int id) {
        System.out.println("UserDaoImpl.queryUser()");
        return null;
    }

    @Override
    public void updateUser(int id, String name, String password) {
        System.out.println("UserDaoImpl.updateUser()");
    }

}

使用静态代理添加安全性检测

package com.dennist.dao.impl;
import com.dennist.dao.UserDao;

public class UserDaoImplProxy implements UserDao{

    private UserDao userDao;
    
    public UserDaoImplProxy(UserDao userDao){
        this.userDao = userDao;
    }
    
    @Override
    public void addUser(String name, String password) {
        checkSecurity();
        this.userDao.addUser(name, password);
    }

    @Override
    public void deleteUser(int id) {
        checkSecurity();
        this.userDao.deleteUser(id);
    }

    @Override
    public String queryUser(int id) {
        checkSecurity();
        return this.userDao.queryUser(id);
    }

    @Override
    public void updateUser(int id, String name, String password) {
        checkSecurity();
        this.userDao.updateUser(id, name, password);
    }

    public void checkSecurity(){
        System.out.println("---------checkSecurity---------");
    }
}

客户端测试代码

package com.dennist.client;
import com.dennist.dao.UserDao;
import com.dennist.dao.impl.UserDaoImpl;
import com.dennist.dao.impl.UserDaoImplProxy;

public class ClientOpt {

    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        UserDaoImplProxy userDaoImplProxy = new UserDaoImplProxy(userDao);
        userDaoImplProxy.addUser("dennisit", "dennisit@163.com");
        
        userDaoImplProxy.deleteUser(5);
    }
}
运行结果:
---------checkSecurity---------
UserDaoImpl.addUser()
---------checkSecurity---------
UserDaoImpl.deleteUser()

 

2.使用JDK的动态代理

需要实现java.lang.reflect.InvocationHandler接口

实例结构图

业务接口定义与实现同上,JDK代理实现代码如下

package com.dennist.dao.impl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SecurityHandler implements InvocationHandler{

    private Object targetObject;
    
    public Object newProxy(Object targetObject){
        this.targetObject = targetObject;
        //面向接口编程,安全认证加在接口上.
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
                               targetObject.getClass().getInterfaces(),
                               this);
    }
    
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        checkSecurity();
        Object result = null;
        try {
            result = method.invoke(this.targetObject, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void checkSecurity(){
        System.out.println("---------checkSecurity---------");
    }
}

客户端测试代码

package com.dennist.client;
import com.dennist.dao.UserDao;
import com.dennist.dao.impl.SecurityHandler;
import com.dennist.dao.impl.UserDaoImpl;

public class ClientOpt {

    public static void main(String[] args) {
        SecurityHandler handler = new SecurityHandler();
        UserDao userDao = (UserDao) handler.newProxy(new UserDaoImpl());
        userDao.addUser("zhangan", "pwd123");
        
        userDao.deleteUser(5);
    }
}
运行结果:
---------checkSecurity---------
UserDaoImpl.addUser()
---------checkSecurity---------
UserDaoImpl.deleteUser()

3.使用springAOP动态织入(使用xml配置)

 

springAOP默认采用JDK的动态代理.

 

项目结构图

业务dao与dao实现同上

定义安全检测方法

package com.spring.dao.impl;

public class SecurityHandler {

    public void checkSecurity() {
        System.out.println("----------checkSecurity()---------------");
    }
}

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"
         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.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
    <bean id="securityHandler" class="com.spring.dao.impl.SecurityHandler"/>           
    <bean id="userDao" class="com.spring.dao.impl.UserDaoImpl"/>
    
    <aop:config>
        <aop:aspect id="securityAspect" ref="securityHandler">
            <aop:pointcut id="allAddMethod" expression="execution(* query*(..))||execution(* add*(..))"/>
            <aop:before pointcut-ref="allAddMethod" method="checkSecurity"/>
        </aop:aspect>
    </aop:config>
    
</beans>

客户端测试

package com.spring.client;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.dao.UserDao;

public class ClientOpt {

    public static void main(String[] args) {
        BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) factory.getBean("userDao");
        userDao.addUser("zhangsan", "pwd123");
        System.out.println("");
        userDao.deleteUser(5);
        System.out.println("");
        userDao.queryUser(3);
    }    
}
运行效果:
----------checkSecurity()---------------
UserDaoImpl.addUser()

UserDaoImpl.deleteUser()

----------checkSecurity()---------------
UserDaoImpl.queryUser()

spring对AOP的支持

如果目标对象实现了接口,默认会采用JDK的动态代理机制实现AOP

如果目标对实现了接口,可以强制使用CGLIB实现AOP

如果目标对象没有实现接口,必须使用CGLIB生成代理,spring会自动在CGLIB和JDK动态代理之间切换.

如何强制使用CGLIB生成代理?

1.添加CGLIB库

2.在spring的配置文件中加入:<aop:aspectj-autoproxy proxy-target-class="true"/>

 

JDK代理和CGLIB代理的区别?

JDK代理只能对实现了接口的类生成代理,而不能针对类

CGLIB是针对类实现代理的,主要对指定的类生成一个子类,并覆盖其中的方法,因为是继承,所以不能使用final来修饰类或方法.

 

转载请注明出处:[http://www.cnblogs.com/dennisit/archive/2013/02/16/2913272.html]

在线交谈

 

原文地址:https://www.cnblogs.com/dennisit/p/2913272.html