静态代理和动态代理

本文通过探讨静态代理和动态代理的概念,展示了如何在Java中应用AOP(面向切面编程)技术,特别是在使用JDK动态代理机制时,通过创建代理类来实现安全验证的前置操作,同时遵循开放封闭原则,避免修改原始方法。具体步骤包括定义接口、实现类、创建安全检查方法、使用静态代理和动态代理实现安全验证,最终通过实例化代理对象并调用方法来执行安全验证与业务逻辑的结合。这种方法适用于那些需要独立服务介入,但与具体方法逻辑无关的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

          对于静态代理和动态代理,了解AOP基于的JDK动态代理机制.

         1.接口UserManager,定义增删改查4个方法.

public interface UserManager {
	public void addUser(String username,String password);
	public void delUser(int userId);
	public String findUserById(int userId);
	public void modifyUser(int userId,String username,String passwrod);

}	

        2.交由UserManagerImpl来实现.

public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {
		System.out.println("---------UserManagerImpl.addUser()---------------");
	}

	public void delUser(int userId) {
		System.out.println("---------UserManagerImpl.delUser()---------------");
	}

	public String findUserById(int userId) {
		System.out.println("---------UserManagerImpl.findUserById()---------------");
		return "张三";
	}

	public void modifyUser(int userId, String username, String passwrod) {
		System.out.println("---------UserManagerImpl.modifyUser()---------------");
	}
}

         3.若要在执行方法前进行安全性的验证(即下面这段代码),该如何做.

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

         4.是这样做?修改每个方法,将安全验证的方法,插入在方法执行前或者执行后?这样好吗,明显不好.修改方法,不仅违背了开放封闭原则,而且需求一旦修改,或浪费很多的时间来修改.

public void addUser(String username, String password) {
           checkSecurity();
	System.out.println("---------UserManagerImpl.addUser()---------------");
	//checkSecurity();
}

      5.那这样做好吗?不修改原来的方法,而是加一个代理,在原来的方法上面包一层,加上安全验证的方法.这种是静态代理的方式,没有违背开放封闭,但是还是有着大量重复工作的问题.所以还是需要改进的.之所以称为静态代理,是因为你还是可以看到代理类的.

public class UserManagerImplProxy implements UserManager {
	private UserManager userManager;
	
	public UserManagerImplProxy(UserManager userManager)
	{
		this.userManager = userManager;
	}
	
	public void addUser(String username, String password) {
		checkSecurity();
		userManager.addUser(username, password);
	}

           public void delUser(int userId) {
		checkSecurity();
		userManager.delUser(userId);

	}

	 //***改查类似
	
	private void checkSecurity()
	{
		System.out.println("---------UserManagerImpl.checkSecurity()---------------");
	}

}

        6.所以现在改成这样,可以吗?改成动态代理,事先并不知道调用的会是哪个方法,但是不管你是哪个方法,都能给你转过去.

          写一个SecurityHandler,实现InvocationHanlder接口.实现接口的invoke方法,参数是一个代理,一个方法,还有参数数组.可以理出,代理,方法和参数数组对应的都是你需要调用的方法的类的代理,方法和参数,也就是目标对象代理和目标方法.invoke方法中,统一添加安全性验证方法,并且将调用方法转向调用目标方法.

           然后就是目标对象和目标对象的代理如何来?需要根据对应的目标对象来生成.声明一个属性targetObject目标对象,传入方式使用createProxyInstance(ObjecttargetObject)传入,并在该方法中将目标对象转为目标对象的代理对象返回.

public class SecurityHandler implements InvocationHandler {
    private Object targetObject;
    public Object createProxyInstance(Object targetObject)
    {
    	this.targetObject=targetObject;
    	 
    	return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
    			targetObject.getClass().getInterfaces(),
    			this);
    }
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		checkSecurity();
		//调用目标方法
		Object ret = method.invoke(targetObject,args);
		return ret;
	}

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

}

        7.代码写完了,如何使用呢?实例化一个SecurityHanlder对象,createProxyInstance,传入UserManagerImpl目标对象,返回UserManagerImpl的代理对象,强制转型为UserManager,使用该方法的addUser方法,就会调到invoke方法上,加上安全性验证的方法,并且去调用目标方法,真正的去添加用户.

public static void main(String[] args) {
         SecurityHandler handler = new SecurityHandler();
    UserManager userManager =(UserManager)handler.createProxyInstance(new UserManagerImpl());
    userManager.addUser("张三","123");
}

        8.这样就可以做到又不用违背开发封闭原则,又可以方便的应对修改.那么对于什么样的情况,可以采用这样的方式来做?对于那种到处都需要使用,但是又和方法本身没有什么关系的独立服务,可以将其提取出来作为一个方法,放到一个类中.

         这个类可以称为Aspect,这个方法可以称为advice.你可以选择将这个方法,放到目标方法执行前或者执行后调用,也可以选择目标方法出了异常再调用.那么目标方法是什么,比如只有增删改才需要安全性验证,查询就不用了,那么目标方法就是增删改的所有方法了,如何做到控制?使用一些表达式如:execution(* add*(..)),这叫做PointCut.这样就可以产生AOP.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值