代理模式初尝试

代理模式
代理模式:为其他对象提供一种代理以控制对这个对象的访问( 代理其实是在原实例前后加了一层处理)。这段话比较官方,但我更倾向于用自己的语言理解:比如A对象要做一件事情,在没有代理前,自己来做,在对A代理后,由A的代理类B来做。代理其实是在原实例前后加了一层处理,这也是AOP的初级轮廓
1.静态代理
基于JDK静态代理 代理类与委托类实现同一接口,并且在代理类中需要硬编码接口
接口IUserDao
package com.fh.test.aop;
public interface IUserDao {
public void find();
public void save();
public void save11(String s);
}
目标类DLUserDao
package com.fh.test.aop;
public class DLUserDao implements IUserDao {
@Override
public void find() {
// TODO Auto-generated method stub
System.out.println("模拟,查询对象");
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("模拟,保存对象");
}
@Override
public void save11(String s) {
// TODO Auto-generated method stub
System.out.println(s);
}
public void save2() {
System.out.println("模拟,保存对象222");
}
代理类DDLUserDao
package com.fh.test.aop;
public class DDLUserDao implements IUserDao {
private IUserDao ddd = new DLUserDao();
@Override
public void find() {
// TODO Auto-generated method stub
System.out.println("开启淡淡的淡淡的淡淡");
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("开启淡淡的淡淡的淡淡");
ddd.save();
System.out.println("关闭淡淡的淡淡的淡淡");
}
@Override
public void save11(String s) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
IUserDao ddddd = new DDLUserDao();
ddddd.save();
}
}
打印

2.动态代理
2.1 基于jdk的动态代理
基于jdk的动态代理代理类与委托类实现同一接口,主要是通过代理类实现InvocationHandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理
要求:目标类和代理类继承同一个接口
接口和目标类不变
代理类NewDDLUserDao
package com.fh.test.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;
public class NewDDLUserDao {
private Object ddlUserDao;
NewDDLUserDao(Object ddl) {
this.ddlUserDao = ddl;
}
public Object getInstance() {
Object proxy = Proxy.newProxyInstance(ddlUserDao.getClass().getClassLoader(), ddlUserDao.getClass().getInterfaces(), new InvocationHandler() {
//args为方法参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
String methodName = method.getName();
Object result = "";
if(Objects.equals(methodName, "save")) {
System.out.println("动态代理开始GOGOGO。。。。");
result = method.invoke(ddlUserDao, args);
System.out.println("动态代理结束ENDEND。。。。");
}else {
result = method.invoke(ddlUserDao, args);
}
return result;
}
});
return proxy;
}
public static void main(String[] args) {
IUserDao dd = new DLUserDao();
//jdk隐藏实现
//class $jdkProxy implements IUserDao{}
IUserDao proxy = (IUserDao) new NewDDLUserDao(dd).getInstance();
proxy.save11("王八哒哒哒哒");
}
}
2.2 Cglib代理
Cglib代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理
委托类CglibUser
package com.fh.test.aop;
public class CglibUser {
public void save() {
System.out.println("Cglib保存对象");
}
}
代理类implements
package com.fh.test.aop;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibPoxyUser implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println("Before:" + method);
Object object = proxy.invokeSuper(obj, arg);
System.out.println("After:" + method);
return object;
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibUser.class);
enhancer.setCallback(new CglibPoxyUser());
CglibUser cglibUser = (CglibUser)enhancer.create();
cglibUser.save();
}
}
使用jdk静态代理以及jdk动态代理和cglib动态代理的优缺点和特点
jdk静态代理
实现简单,容易理解,代理类需要硬编码接口,在实际应用中可能会导致重复编码,浪费存储空间并且效率很低,
jdk动态代理
不需要硬编码接口,代码复用率高,只能够代理实现了接口的委托类,底层使用反射机制进行方法的调用
cglib动态代理
可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口,不能对final类以及final方法进行代理,底层将方法全部存入一个数组中,通过数组索引直接进行方法调用
2.基于Spring动态代理
配置文件springAop.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- dao实例加入容器 -->
<bean id="user1Dao" class="com.fh.test.aop.SpringUser1Dao"></bean>

<!-- dao实例加入容器 -->
<bean id="userDao" class="com.fh.test.aop.SpringUserDao"></bean>

<!-- 实例化切面类 -->
<bean id="transactionAop" class="com.fh.test.aop.SpringProxy"></bean>

<!-- Aop相关配置 -->
<aop:config>
<!-- 切入点表达式定义 -->
<aop:pointcut expression="execution(* com.fh.test.aop.*Dao.*(..))" id="transactionPointcut"/>
<!-- 切面配置 -->
<aop:aspect ref="transactionAop">
<!-- 【环绕通知】 -->
<aop:around method="arroud" pointcut-ref="transactionPointcut"/>
<!-- 【前置通知】 在目标方法之前执行 -->
<aop:before method="beginTransaction" pointcut-ref="transactionPointcut" />
<!-- 【后置通知】 -->
<aop:after method="commit" pointcut-ref="transactionPointcut"/>
<!-- 【返回后通知】 -->
<aop:after-returning method="afterReturing" pointcut-ref="transactionPointcut"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="transactionPointcut"/>
</aop:aspect>
</aop:config>
</beans>
接口SpringIUserDao
package com.fh.test.aop;

public interface SpringIUserDao {
public void save();
}
接口实现类 SpringUserDao
package com.fh.test.aop;
public class SpringUserDao implements SpringIUserDao {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("我是实现了SpringIUserDao的委托类哦");
}
}
没有实现接口类SpringUser1Dao
package com.fh.test.aop;
public class SpringUser1Dao {
public void save(){
System.out.println("除了Object没有继承的类,也未有实现接口");
}
}
代理类SpringProxy 分别使用Junit 和main方法测试
package com.fh.test.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringProxy {
public void beginTransaction() {
System.out.println("[前置通知] 开启事务..");
}
public void commit() {
System.out.println("[后置通知] 提交事务..");
}
public void afterReturing(){
System.out.println("[返回后通知]");
}
public void afterThrowing(){
System.out.println("[异常通知]");
}
public void arroud(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("[环绕前:]");
pjp.proceed(); // 执行目标方法
System.out.println("[环绕后:]");
}
@SuppressWarnings("resource")
@Test
public void test() {
ApplicationContext aContext=new ClassPathXmlApplicationContext("classpath:springAop.xml");
SpringIUserDao springuserDao =(SpringIUserDao) aContext.getBean("userDao");
System.out.println(springuserDao.getClass());
springuserDao.save();
}
//@Test
public void test1() {
@SuppressWarnings("resource")
ApplicationContext aContext1=new ClassPathXmlApplicationContext("classpath:springAop.xml");
SpringUser1Dao springuserDao1 =(SpringUser1Dao) aContext1.getBean("user1Dao");
System.out.println(springuserDao1.getClass());
springuserDao1.save();
}
private static ApplicationContext aContext=new ClassPathXmlApplicationContext("classpath:springAop.xml");
public static void main(String[] args) {
SpringIUserDao springuserDao =(SpringIUserDao) aContext.getBean("userDao");
System.out.println(springuserDao.getClass());
springuserDao.save();
SpringUser1Dao springuserDao1 =(SpringUser1Dao) aContext.getBean("user1Dao");
System.out.println(springuserDao1.getClass());
springuserDao1.save();
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值