uniapp开发app框架在提升开发效率中的独特优势与应用探索
713
2023-07-11
Spring IOC和aop的原理及实例详解
这篇文章主要介绍了Spring IOC和aop的原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。特点是面向接口编程,松耦合。
1:IOC(控制反转) 别名(DI:依赖注入)
首先来一段ioc的实现原来代码:
public class ClassPathXmlApplicationContext implements BeanFactory {
private Map
//IOC Inverse of Control DI Dependency Injection
public ClassPathXmlApplicationContext() throws Exception {
SAXBuilder sb=new SAXBuilder();
//解析xml配置文件
Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
Element root=doc.getRootElement(); //获取根元素
List list=root.getChildren("bean");//根元素下的子元素
for(int i=0;i Element element=(Element)list.get(i); String id=element.getAttributeValue("id"); String clazz=element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); //反射获得实例 System.out.println(id); System.out.println(clazz); beans.put(id, o); //注入bean属性 for(Element propertyElement : (List String name = propertyElementGMapzjUl.getAttributeValue("name"); //userDAO String bean = propertyElement.getAttributeValue("bean"); //u Object beanObject = beans.get(bean);//UserDAOImpl instance String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); System.out.println("method name = " + methodName); Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); m.invoke(o, beanObject); } } } public Object getBean(String id) { return beans.get(id); } } //xml文件 以上代码实现了将UserDAOImpl注入到userService. 值得注意的是:以上操作都是GMapzjUlspring帮我们实现的,我们只需要理解如何配置即可。 spring还提供了bean的生存周期和范围属性: scope:singleton(单例,即每次调用的对象都为同一个)。 prototype(原型,即以bean对象为原型,每次new一个新对象出来) init-method="init" destroy-method="destroy" lazy-init="true"(延迟初始化bean,即spring启动时,不初始化bean,当需要使用时才实例化,作用:但spring启动缓慢时可使用) 现在基本都是用注解实现,但只要能明白spring是如何实现bean的注入,基本原理都是一样的。spring在中间的作用就是帮我们实现元素之前的注入,谁注入到谁就需要用到不同的注解了。 AOP(切面编程) 首先还是先来一段代码 定义一个InvocationHandler的实现类 public class UserServiceTest { @Test public void testAdd() throws Exception { BeanFactory applicationContext = new ClassPathXmlApplicationContext(); UserService service = (UserService)applicationContext.getBean("userService"); User u = new User(); u.setUsername("zhangsan"); u.setPassword("zhangsan"); service.add(u); } @Test public void testProxy() { UserDAO userDAO = new UserDAOImpl(); LogInterceptor li = new LogInterceptor(); li.setTarget(userDAO); UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li); userDAOProxy.delete(); userDAOProxy.save(new User()); } 调用测试类,service和DAO实现类没有贴出来,就是打印一句话出来表现方法执行了。 public class LogInterceptor implements InvocationHandler { private Object target; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public void beforeMethod(Method m) { System.out.println(m.getName() + " start"); } @Override public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { beforeMethod(m); m.invoke(target, args); return null; } } 以上代码简单的实现了一个动态代理,并执行了自己的一段逻辑。 那么aop是如何实现切面编程的呢,就是通过动态代理。当然这也是spring来实现的,而我们需要做的就是知道如何编写编织语法。 JoinPoint:切入点 PointCut: 切入点的集合 Aspect:切面 Advice: 相当于Aspect的before Around:周围,环绕(需要带参数ProceedingJoinPoint jp) 需要注意的是:被产生代理的对象需要现实接口spring才能产生代理对象,默认使用java se 中的 InvocationHandler 和 proxy 两个类产生代理对象,若没有实现接口,则需要另外引入一个jar包(cglib-nodep-2.1_3.jar);他是通过二进流的方式产生代理对象。 那么spring 帮我们做了什么? 1:充分利用java se 中的反射机制帮助我们对对象的注入,即 IOC, 2: 也是java se 中的动态代理帮助我们实现 切面编程,当然我们也需要熟悉一下asceptj 的切入语法。这就是aop。 所以这里可以总结一下,java se 的特点有反射,动态代理,(这里面必然会用到多态,动态绑定)
Element element=(Element)list.get(i);
String id=element.getAttributeValue("id");
String clazz=element.getAttributeValue("class");
Object o = Class.forName(clazz).newInstance(); //反射获得实例
System.out.println(id);
System.out.println(clazz);
beans.put(id, o);
//注入bean属性
for(Element propertyElement : (List
String name = propertyElementGMapzjUl.getAttributeValue("name"); //userDAO
String bean = propertyElement.getAttributeValue("bean"); //u
Object beanObject = beans.get(bean);//UserDAOImpl instance
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
System.out.println("method name = " + methodName);
Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
m.invoke(o, beanObject);
}
}
}
public Object getBean(String id) {
return beans.get(id);
}
}
//xml文件
以上代码实现了将UserDAOImpl注入到userService.
值得注意的是:以上操作都是GMapzjUlspring帮我们实现的,我们只需要理解如何配置即可。
spring还提供了bean的生存周期和范围属性:
scope:singleton(单例,即每次调用的对象都为同一个)。 prototype(原型,即以bean对象为原型,每次new一个新对象出来)
init-method="init" destroy-method="destroy" lazy-init="true"(延迟初始化bean,即spring启动时,不初始化bean,当需要使用时才实例化,作用:但spring启动缓慢时可使用)
现在基本都是用注解实现,但只要能明白spring是如何实现bean的注入,基本原理都是一样的。spring在中间的作用就是帮我们实现元素之前的注入,谁注入到谁就需要用到不同的注解了。
AOP(切面编程)
首先还是先来一段代码
定义一个InvocationHandler的实现类
public class UserServiceTest {
@Test
public void testAdd() throws Exception {
BeanFactory applicationContext = new ClassPathXmlApplicationContext();
UserService service = (UserService)applicationContext.getBean("userService");
User u = new User();
u.setUsername("zhangsan");
u.setPassword("zhangsan");
service.add(u);
}
@Test
public void testProxy() {
UserDAO userDAO = new UserDAOImpl();
LogInterceptor li = new LogInterceptor();
li.setTarget(userDAO);
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
userDAOProxy.delete();
userDAOProxy.save(new User());
}
调用测试类,service和DAO实现类没有贴出来,就是打印一句话出来表现方法执行了。
public class LogInterceptor implements InvocationHandler {
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public void beforeMethod(Method m) {
System.out.println(m.getName() + " start");
}
@Override
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
beforeMethod(m);
m.invoke(target, args);
return null;
}
}
以上代码简单的实现了一个动态代理,并执行了自己的一段逻辑。
那么aop是如何实现切面编程的呢,就是通过动态代理。当然这也是spring来实现的,而我们需要做的就是知道如何编写编织语法。
JoinPoint:切入点
PointCut: 切入点的集合
Aspect:切面
Advice: 相当于Aspect的before
Around:周围,环绕(需要带参数ProceedingJoinPoint jp)
需要注意的是:被产生代理的对象需要现实接口spring才能产生代理对象,默认使用java se 中的 InvocationHandler 和 proxy 两个类产生代理对象,若没有实现接口,则需要另外引入一个jar包(cglib-nodep-2.1_3.jar);他是通过二进流的方式产生代理对象。
那么spring 帮我们做了什么?
1:充分利用java se 中的反射机制帮助我们对对象的注入,即 IOC,
2: 也是java se 中的动态代理帮助我们实现 切面编程,当然我们也需要熟悉一下asceptj 的切入语法。这就是aop。
所以这里可以总结一下,java se 的特点有反射,动态代理,(这里面必然会用到多态,动态绑定)
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~