zoukankan      html  css  js  c++  java
  • 对spring的IOC和aop的学习总结

    Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。特点是面向接口编程,松耦合。

    1:IOC(控制反转)  别名(DI:依赖注入)

    首先来一段ioc的实现原来代码:

     1 public class ClassPathXmlApplicationContext implements BeanFactory {
     2     
     3     private Map<String , Object> beans = new HashMap<String, Object>();
     4     
     5     //IOC Inverse of Control DI Dependency Injection
     6     public ClassPathXmlApplicationContext() throws Exception {
     7         SAXBuilder sb=new SAXBuilder();
     8         //解析xml配置文件
     9         Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
    10         Element root=doc.getRootElement(); //获取根元素
    11         List list=root.getChildren("bean");//根元素下的子元素
    12         for(int i=0;i<list.size();i++) {
    13            Element element=(Element)list.get(i);
    14            String id=element.getAttributeValue("id");
    15            String clazz=element.getAttributeValue("class");
    16            Object o = Class.forName(clazz).newInstance(); //反射获得实例
    17            System.out.println(id);
    18            System.out.println(clazz);
    19            beans.put(id, o);
    20            //注入bean属性
    21            for(Element propertyElement : (List<Element>)element.getChildren("property")) {
    22                String name = propertyElement.getAttributeValue("name"); //userDAO
    23                String bean = propertyElement.getAttributeValue("bean"); //u
    24                Object beanObject = beans.get(bean);//UserDAOImpl instance
    25                
    26                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
    27                System.out.println("method name = " + methodName);
    28                
    29                Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
    30                m.invoke(o, beanObject);  
    31            }
    32         }  
    33     }
    34 
    35     public Object getBean(String id) {
    36         return beans.get(id);
    37     }
    38 }
    //xml文件
    1
    <beans> 2 <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" /> 3 <bean id="userService" class="com.bjsxt.service.UserService" > 4 <property name="userDAO" bean="u"/> 5 </bean> 6 7 </beans>

    以上代码实现了将UserDAOImpl注入到userService.

    值得注意的是:以上操作都是spring帮我们实现的,我们只需要理解如何配置即可。

    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实现类没有贴出来,就是打印一句话出来表现方法执行了。

     1 public class LogInterceptor implements InvocationHandler {
     2     private Object target;
     3     public Object getTarget() {
     4         return target;
     5     }
     6     public void setTarget(Object target) {
     7         this.target = target;
     8     }
     9 
    10     public void beforeMethod(Method m) {
    11         System.out.println(m.getName() + " start");
    12     }
    13 
    14     @Override
    15     public Object invoke(Object proxy, Method m, Object[] args)
    16             throws Throwable {
    17         beforeMethod(m);
    18         m.invoke(target, args);
    19         return null;
    20     }
    21 }

    以上代码简单的实现了一个动态代理,并执行了自己的一段逻辑。

    那么aop是如何实现切面编程的呢,就是通过动态代理。当然这也是spring来实现的,而我们需要做的就是知道如何编写编织语法。

    JoinPoint:切入点

    PointCut: 切入点的集合

    Aspect:切面

    Advice: 相当于Aspect的before

    Around:周围,环绕(需要带参数ProceedingJoinPoint jp)

    需要注意的是:被产生代理的对象需要现实接口spring才能产生代理对象,默认使用java se 中的 InvocationHandlerproxy  两个类产生代理对象,若没有实现接口,则需要另外引入一个jar包(cglib-nodep-2.1_3.jar);他是通过二进流的方式产生代理对象。

    那么spring 帮我们做了什么?

    1:充分利用java se 中的反射机制帮助我们对对象的注入,即 IOC,

    2:  也是java se 中的动态代理帮助我们实现 切面编程,当然我们也需要熟悉一下asceptj 的切入语法。这就是aop。

    所以这里可以总结一下,java se 的特点有反射,动态代理,(这里面必然会用到多态,动态绑定)

  • 相关阅读:
    Java内存模型与volatile
    Struts2验证框架的注意事项
    利用Java编写简单的WebService实例
    加速Java应用开发速度1——加速spring/hibernate应用调试时启动速度
    Java关键字synchronized详解
    JAVA对象的序列化与反序列化
    加速Java应用开发速度3——单元/集成测试+CI
    java程序性能优化之找出内存溢出元凶
    加速Java应用开发速度2——加速项目调试启动速度
    java实现动态切换上网IP (ADSL拨号上网)
  • 原文地址:https://www.cnblogs.com/yunian139/p/10511993.html
Copyright © 2011-2022 走看看