First try of proxy mode

proxy mode
Proxy mode: Provide a proxy for other objects to control access to this object ( The proxy actually adds a layer of processing before and after the original instance ). This passage is more official, but I prefer to understand it in my own language: For example, if object A wants to do something, before there is no proxy, it will do it by itself. After proxying to A, it will be done by the proxy class B of A. The proxy actually adds a layer of processing before and after the original instance, which is also the primary outline of AOP
1. Static proxy
Based on JDK static proxy proxy class and delegate class implement the same interface, and the interface needs to be hard-coded in the proxy class
Interface IUserDao
package com.fh.test.aop;
public interface IUserDao {
public void find();
public void save();
public void save11(String s);
}
target class DLUserDao
package com.fh.test.aop;
public class DLUserDao implements IUserDao {
@Override
public void find() {
// TODO Auto-generated method stub
System.out.println("Simulation, query object");
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("Simulate, save object");
}
@Override
public void save11(String s) {
// TODO Auto-generated method stub
System.out.println(s);
}
public void save2() {
System.out.println("Simulation, save object 222");
}
Proxy class 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();
}
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325519787&siteId=291194637