Spring+Hibernate:Aop相关概念与动态代理
来源:互联网 发布:手机淘宝旺铺首页装修 编辑:程序博客网 时间:2024/06/10 19:23
本博文也是属于学习总结性博文,主要来学习Spring+Hibernate的声明式事务。为此,我们从分三步进行:
- Spring + Hibernate : Aop相关概念与动态代理;
- Spring + Hibernate : 声明式事务;
- AOP 概念
Aspect Oriented Programming 面向横切面的编程:
横切性关注点: 是一种遍布在系统各个角落的、与我们的业务逻辑相结合的不是太紧密的、独立的服务,例如安全性检查、事务等。
而我们的AOP主要是处理这些横切面关注点;
- Cross Cutting concern :
- 横切性关注点,是一种遍布在系统流程之中的独立服务;
- Aspect :
- 对这些横切性关注点的模块化,也就是将这些横切性关注点封装成一个类;
- Advice :
- 对这些横切性关注点的具体实现,及其使用方式,在业务流程方法调用之前、之后和抛出异常等使用方式。
- Jointpoint :
- 连接点,对Spring来说就是方法调用,也可以理解成Advice执行的时机。Jointpoint 分为方法调用和属性修改,对Spring来说它只支持方法调用;
Pointcut :
- 对Advice应用范围进行限定,定义了Pointcut应用到那些Jointpoint上;
Weave :
- 将Advice应用到目标对象上的过程,成为织入;
TargetObject :
- 目标对象,Advice 应用的对象;
Proxy :
- Spring AOP 默认使用的代理时JDK 的动态代理,我们也可以使用CGLIB代理,两者的区别: JDK动态代理只能对实现了接口的累进行代理,而CGLIB可以对所有的类进行代理,因为它使用了继承的方式来实现代理;
Introduction :
- 引入,动态地为类添加方法;
- 通过如下简单示例对静态代理,动态代理和AOP进行比较说明,
项目结构:
2.1 静态代理,com.staticProxy.manager
interface UserManager:
package com.staticProxy.manager;//只有两个简单的方法 添加用户和查找用户;public interface UserManager { public void addUser(String name,String password); public Object findUser(String id);}
Class UserManagerImpl:
package com.staticProxy.manager;public class UserManagerImpl implements UserManager { @Override public void addUser(String name, String password) { System.out.println("UserManagerImpl.add()"+ name+" "+password); } @Override public Object findUser(String id) { System.out.println("UserManagerImpl.findUser()"+id); return "User1"; }}
假如现在的业务发生改变,我们在添加用户和查找用户时,都要进行安全性检查,如何解决这个问题;奔着对扩展开放,对修改关闭的原则,我们怎么修改,引入静态代理模式:
Class UserManagerImplProxy
package com.staticProxy.manager;public class UserManagerImplProxy implements UserManager { //使用静态代理的关键是拿到代理目标的引用, //在此我们通过构造函数的方式拿到;也可以setter getter; private UserManager userManager; //通过构造函数拿到被代理对象的引用; public UserManagerImplProxy(UserManager userManager){ this.userManager = userManager; } @Override public void addUser(String name, String password) { //增加安全性检查操作; checkSecurity(); userManager.addUser(name, password); } @Override public Object findUser(String id) { //增加安全性检查操作 checkSecurity(); userManager.findUser(id); return null; } //将安全性检查的操作封装成一个方法; private void checkSecurity(){ System.out.println("---checkSecurity()---"); }}
测试静态代理方法
public class ProxyTest extends TestCase { public void testStaticProxy(){ //将被代理对象的引用传入; UserManager userManager = new UserManagerImplProxy(new UserManagerImpl()); userManager.addUser("zhangsan", "123"); userManager.findUser("abc"); }}
分析:
1. 在代理对象中,我们得为每个方法手动的添加安全性检查代码 checkSecurity()
,如果代理类中的方法很多,这就会很麻烦;
2. 如果UserManager有多个实现呢,我们需要为每个实现创建一个代理对象,并在每个方法上加安全性检查操作
3. 在调用时,
UserManager manager = new UserManagerImpl();
变成了:
UserManager manager = new UserManagerImplProxy(new UserManagerImpl());
引入了工厂字眼,代码复杂了;
如何为实现了某些接口的类动态的创建一个代理,并且在代用这些实现方法时,自动的加上安全性检查代码呢?
2.2 动态代理-JDK的动态代理 com.dynamicProxy.manager
interface UserManager 和 UserManagerImpl和以前一样
package com.dynamicProxy.manager;public interface UserManager { public void addUser(String name,String password); public Object findUser(String id);}
package com.dynamicProxy.manager;public class UserManagerImpl implements UserManager { @Override public void addUser(String name, String password) { System.out.println("UserManagerImpl.add()"+ name+" "+password); } @Override public Object findUser(String id) { System.out.println("UserManagerImpl.findUser()"+id); return "User2"; }}
动态代理类:SecurityHandler
package com.dynamicProxy.manager;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//JDK动态代理必须实现InvocationHandler接口重写invoke方法public class SecurityHandler implements InvocationHandler { //step 1: 拿到要被代理的目标对象 targetObject private Object targetObject; //setp 2: 生成代理对象; // 在生成代理对象的同时,我们将被代理的目标对象转入,当然有多种传入方式; //三个参数:ClassLoader loder: 类加载器,使用目标对象的类加载器; //Class<?>[] interfs:目标对象实现的接口,如果这个目标有五个接口,会为每个接口创建一个代理; //InvocationHander h: 上两步已经将代理对象生产,那么我们在调用代理的方法时,代理对象会自动调用InvocationHander的invoke方法; public Object createDynamicProxy(Object targetObject){ this.targetObject = targetObject; //使用Proxy生成代理; Object dynamicProxy = Proxy.newProxyInstance( targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this ); return dynamicProxy; } //调用代理的每个方法都会自动转到InvocationHandler的invoke方法,因为在 //代理对象中有InvocationHandler的引用this @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //安全性检查代码,会动态为每个方法加上; checkSecurity(); //实际调用目标对象的方法; //obj: 要调用的目标对象 // args: 目标对象的参数,这个由代理自动传过来; Object result = method.invoke(targetObject, args); return result; } private void checkSecurity(){ System.out.println("-----------checkSecurity()-danymicProxy------------"); }}
测试类:
import com.dynamicProxy.manager.SecurityHandler;import com.staticProxy.manager.UserManager;import com.staticProxy.manager.UserManagerImpl;import com.staticProxy.manager.UserManagerImplProxy;import junit.framework.TestCase;public class ProxyTest extends TestCase { public void testDynamicProxy(){ UserManager userManager = (UserManager) new SecurityHandler().createDynamicProxy(UserManagerImpl()); userManager.addUser("LiSi", "12306"); userManager.findUser("001"); }}
Spring AOP对此进行了更好的封装,
2.3 AOP声明式服务:AspectJ 的annotation注解方式,
interface UserManager 和 UserManagerImpl和以前一样
class SecurityAspectAnno
package com.aspect.manager;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;// Step 1: 将横切性关注点封装成一个类;//声明这是一个Aspcet@Aspectpublic class SecurityAspectAnno { //Step 2: 定义Advice应用的范围:Pointcut //定义一个Pointcut,范围用execution(正则表达),和名称addUserManager() @Pointcut("execution(* com.aspect.manager.UserManager.*(..))") private void addUserManager(){}; // Step 3: 定义Advice; //定义advice,并关联到相应的Pointcut订阅的Jointpoint上; @Before("addUserManager()") private void checkSecurity(){ System.out.println("-----------checkSecurity()-aspectJ------------"); }}
最后告诉Spring, 我们用了aspectj的annotation
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"> <!-- 开启AspectJ的annotation --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> <bean id="userManagerImpl1" class="com.aspect.manager.UserManagerImpl"/> <bean id="securityAspectAnno" class="com.aspect.manager.SecurityAspectAnno"/></beans>
2.3 AOP声明式服务:XML配置文件,
class SecurityAspectCfg
package com.aspect.manager;//简简单单的不需要配置任何注释东西了;public class SecurityAspectCfg { private void checkSecurityCfg(){ System.out.println("---checkSecurity()-Cfg---"); }}
我们在配置文件中声明Aspect相关内容;
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <bean id="userManagerImpl2" class="com.aspect.manager.UserManagerImpl"/> <bean id="securityAspectCfg" class="com.aspect.manager.SecurityAspectCfg"/> <aop:config> <aop:aspect id="checkAspect" ref="securityAspectCfg"> <aop:pointcut expression="execution(* com.aspect.manager.UserManager.*(..))" id="addAddMethod"/> <aop:before method="checkSecurityCfg" pointcut-ref="addAddMethod"/> </aop:aspect> </aop:config></beans>
测试类:
import org.springframework.beans.factory.BeanFactory;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.aspect.manager.UserManager;import junit.framework.TestCase;public class AspectJTest extends TestCase{ private BeanFactory factory; protected void setUp() throws Exception { factory = new ClassPathXmlApplicationContext("applicationContext-aspectj.xml"); } protected void tearDown() throws Exception { } public void testAspectJAnno(){ UserManager userManager = (UserManager) factory.getBean("userManagerImpl2"); userManager.addUser("zz","23"); userManager.findUser("121"); }}
That’s all, thank you for your consideration. And, welcome any commonet.
- Spring+Hibernate:Aop相关概念与动态代理
- spring基础概念AOP与动态代理理解
- 动态代理与spring AOP
- Spring AOP与动态代理
- Spring AOP 静态代理与动态代理
- Java动态代理与AOP概念
- Spring AOP与Java动态代理
- Spring - 动态代理 与 AOP 理解
- JDK动态代理与Spring AOP
- Spring Aop 动态代理
- Spring AOP动态代理
- Spring AOP 动态代理
- spring aop动态代理
- Spring(AOP动态代理)
- spring AOP 动态代理 jkd动态代理和cglib动态代理 hibernate使用cglib延迟加载
- Spring AOP中的JDK动态代理与CGLIB代理
- 黑马程序员--09.动态与代理AOP--01【代理的作用与概念】【动态代理与AOP】
- 动态代理与AOP
- 嵌入式linux之hotplug_uevent驱动(热拔插)
- 嵌入式系统知识及接口技术总结
- ViewPager获取网络上的图片
- 使用mysql5.7 workbench创建ER视图以及查看表的外键等信息
- 《tensorflow实战》6——强化学习之策略网络
- Spring+Hibernate:Aop相关概念与动态代理
- rails 日常总结(一)
- 数据库连接池
- iOS设置状态栏样式,显示控制,statusBarStyle, statusBar
- 在监听器中使用@Autowried调用service层包null的解决方案
- 商城支付~支付宝~加密
- 不一样的C语言-auto,register,static,extern
- tail语法格式
- http请求返回状态码详解