.NET领域最为流行的IOC框架之一Autofac

 

一、前言

Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也是用的Autofac。

Orchad和Nopcommerce在用Autofac的时候进行封装,看过源码的都知道Autafac使用简单,功能强大。

建议下载Orchad和Nopcommerce学习下源码:附上下载地址

http://www.orchardproject.net/

http://www.nopcommerce.com/

和其他IOC对比:

Unity:微软patterns&practicest团队开发的IOC依赖注入框架,支持AOP横切关注点。

MEF(Managed Extensibility Framework):是一个用来扩展.NET应用程序的框架,可开发插件系统。

Spring.NET:依赖注入、面向方面编程(AOP)、数据访问抽象,、以及ASP.NET集成。

PostSharp:实现静态AOP横切关注点,使用简单,功能强大,对目标拦截的方法无需任何改动。

Autofac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

下面介绍Autofac的使用

二、Autofac使用

新建一个mvc的项目,使用nuget安装Autofac,需要安装Autofac和Autofac ASP.NET MVC5 Intergration

安装完成后引用里面就多了Autofac.dll和Autofac.Intergration.MVC,如果是在webApi里使用Autofac需要安装Autofac ASP.NET Web API2.2 Intergration 才可以。

新建一个person实体类

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

新建一个person仓储接口

    public interface IPersonRepository
    {
        IEnumerable<Person> GetAll();
        Person Get(int id);
        Person Add(Person item);
        bool Update(Person item);
        bool Delete(int id);
    }

新建实现

 public class PersonRepository : IPersonRepository
    {
        List<Person> person = new List<Person>();

        public PersonRepository()
        {
            Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中国上海" });
        }
        public IEnumerable<Person> GetAll()
        {
            return person;
        }
        public Person Get(int id)
        {
            return person.Find(p => p.Id == id);
        }
        public Person Add(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            person.Add(item);
            return item;
        }
        public bool Update(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = person.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            person.RemoveAt(index);
            person.Add(item);
            return true;
        }
        public bool Delete(int id)
        {
            person.RemoveAll(p => p.Id == id);
            return true;
        }
    }

Global属性注入

 public class MvcApplication : System.Web.HttpApplication
    {
        private void SetupResolveRules(ContainerBuilder builder)
        {
            builder.RegisterType<PersonRepository>().As<IPersonRepository>();
        }
        protected void Application_Start()
        {
            var builder = new ContainerBuilder();
            SetupResolveRules(builder);
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

最好获取数据结果;

三、总结

文中只是给出了一个简单的注入实现,剩下的可以自己去研究下,构造函数注入,方法注入

泛型注入,所有程序集注入,都可以看下,

也可以把文章开头的两个开源的项目下载下来研究里面的Autofac注入方式。

WebAPI2使用Autofac实现IOC属性注入完美解决方案

 

一、前言

只要你是.NETer你一定IOC,IOC里面你也会一定知道Autofac,上次说了在MVC5实现属性注入,今天实现在WebApi2实现属性注入,顺便说一下autofac的程序集的注入方式,都会在后面的代码里面有提现

在WebAPI2使用Autofac注入的时候大多数人会出现如下问题:

未能加载文件或程序集“System.Web.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

截图如下:

这个是Autofac强依赖造成的,比较坑的。解决办法如下。

Nuget添加Microsoft.AspNet.WebApi

或通过NuGet 程序包管理器控制台添加:

Install-Package Microsoft.AspNet.WebApi

Update-Package Microsoft.AspNet.WebApi -reinstall(存在)

原因:我们新建的是一个空的MVC项目,缺少引用

先上个结构图,结构图只是为了说明webAPI如何简单使用Autofac实现属性注入。

属性注入存在安全隐患,官方建议使用构造函数注入。

下面说下具体实现:

二、代码实现

1、新建一个WebAPI.Entity类库,新建一个Person.cs类

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

2、新建WebAPI.IRepository类库,新建一个IPersonRepository类

    public interface IPersonRepository
    {
        List<Person> GetAll();
        Person Get(int id);
        Person Add(Person item);
        bool Update(Person item);
        bool Delete(int id);
    }

3、新建WebAPI.Repository类库,新建一个PersonRepository类实现IPersonRepository接口

public class PersonRepository : IPersonRepository
    {
        List<Person> person = new List<Person>();

        public PersonRepository()
        {
            Add(new Person { Id = 1, Name = "joye.net1", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 2, Name = "joye.net2", Age = 18, Address = "中国上海" });
            Add(new Person { Id = 3, Name = "joye.net3", Age = 18, Address = "中国上海" });
        }
        public List<Person> GetAll()
        {
            return person;
        }
        public Person Get(int id)
        {
            return person.Find(p => p.Id == id);
        }
        public Person Add(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            person.Add(item);
            return item;
        }
        public bool Update(Person item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            int index = person.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            person.RemoveAt(index);
            person.Add(item);
            return true;
        }
        public bool Delete(int id)
        {
            person.RemoveAll(p => p.Id == id);
            return true;
        }
    }

4、新建WebAPI.IServices类库,新建IPersonServices接口

    public interface IPersonServices
    {
        List<Person> GetAll();
    }

5、IPersonServices接口在WebAPI.Services类库里面PersonServices实现

    public class PersonServices : IPersonServices
    {
        //程序集属性注入
        public IPersonRepository iPerson;

        public List<Person> GetAll()
        {
            return iPerson.GetAll();
        }
    }

6、新建一个WebAPI项目WebAPI,新建AutoFacBootStrapper类,nuget安装autofac

public class AutoFacBootStrapper
    {
        public static void CoreAutoFacInit()
        {
            var builder = new ContainerBuilder();
            HttpConfiguration config = GlobalConfiguration.Configuration;

            SetupResolveRules(builder);

            ////注册所有的Controllers
            //builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            //注册所有的ApiControllers
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            var container = builder.Build();
            //注册api容器需要使用HttpConfiguration对象
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }

        private static void SetupResolveRules(ContainerBuilder builder)
        {
            //WebAPI只用引用services和repository的接口,不用引用实现的dll。
            //如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
            var iServices = Assembly.Load("WebAPI.IServices");
            var services = Assembly.Load("WebAPI.Services");
            var iRepository = Assembly.Load("WebAPI.IRepository");
            var repository = Assembly.Load("WebAPI.Repository");

            //根据名称约定(服务层的接口和实现均以Services结尾),实现服务接口和服务实现的依赖
            builder.RegisterAssemblyTypes(iServices, services)
              .Where(t => t.Name.EndsWith("Services"))
              .AsImplementedInterfaces();

            //根据名称约定(数据访问层的接口和实现均以Repository结尾),实现数据访问接口和数据访问实现的依赖
            builder.RegisterAssemblyTypes(iRepository, repository)
              .Where(t => t.Name.EndsWith("Repository"))
              .AsImplementedInterfaces();
        }
    }

7、程序启动注入

        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //程序启动注入
            AutoFacBootStrapper.CoreAutoFacInit();
        }

8.接口调用数据

        public IPersonServices IServices { get; set; }
        // GET api/<controller>
        public IEnumerable<string> Get()
        {
            var list = IServices.GetAll();
            return new string[] { "value1", "value2" };
        }

9.运行访问api/values/,打个断点看下搞定

三、总结

autofac确实用起来很方便,上面只是简单的实现,如果想深入学习可以下载我上一个文章提供的两个开源的项目可以学习下,也可以到autofac官网去了解下。

最近在看相关文章,很多都太专业化了没怎么看懂,这是自己现在对IoC的一些理解,记录下来,要不然时间一久,也就忘了。

自己对IoC模式理解还很浅,希望得到各位的指点。

代码下载:

https://yunpan.cn/c6QCURhYmGcP9 (提取码:e97a)

AutoFac容器初步

 

转载请注明出处,AutoFac:最流行的依赖注入和IOC框架,轻量且高性能,对项目代码几乎无任何侵入性。

那么我们怎么来使用这样一个框架呢

1、在引用项右击,选择Nuget管理,这里我们要导入两个包

一个是AutoFac包,另外一个就是Autofac ASP.NET MVC5 Intergration

在webapi里面使用的话我们需要添加一个Autofac ASP.NET Web API2.2 Intergration 才可以。

2.Global.asax.cs属性注入,配置IOC容器,我这里配置的是通用的以I开头的Repository(仓库类)

#region autofac IOC容器配置
            var builder = new ContainerBuilder();

            //注册所有的controller
            builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
            //注册所有模块module
            builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());

            var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();

            //注册所有继承IDependency接口的类
            builder.RegisterAssemblyTypes(assemblys)
            .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract);

            //注册服务,所有IxxxxRepository=>xxxxRepository
            builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces();

            var container = builder.Build();

            BaseInfo._container = container;

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            #endregion

3.新建实体基类以及实体类,也就是创建数据模型

base类:

public class BaseEntity
    {
        [NotMapped]
        [PropertyModelBinder("start")]
        public int pageIndex { get; set; }

        [NotMapped]
        [PropertyModelBinder("length")]
        public int pageSize { get; set; }

        [NotMapped]
        public string draw { get; set; }

        [NotMapped]
        public List<Orderby> order { get; set; }

        [NotMapped]
        public List<Datacolumn> columns { get; set; }

    }

   public class Orderby {
       public string column { get; set; }

       public string dir { get; set; }
   }

   public class Datacolumn {
       public string data { get; set; }

       public string name { get; set; }

       public bool searchable { get; set; }

       public bool orderable { get; set; }
   }

实体类:

public class User : BaseEntity
    {
       public User() {
           RoleList = new List<Role>();
           MessageList = new List<UserMappingMessage>();
       }
       public int UserID { get; set; }

       public string UserName { get; set; }

       public string UserPassword {get;set;}

       public string UserReallyname {get;set;}

       public string HeadPortrait { get; set; }

       public string MobilePhone { get; set; }

       public string Email { get; set; }

       public int DepartmentID {get;set;}

       public bool IsEnable {get;set;}

       public DateTime CreateTime {get;set;}

       public DateTime? UpdateTime {get;set;}

       public string Remark { get; set; }

       public ICollection<Role> RoleList { get; set; }

       //接收消息列表
       public ICollection<UserMappingMessage> MessageList { get; set; }

       public Dictionary Department { get; set; }

       //发送消息列表
       public List<Message> Messages { get; set; }

    }

4.创建仓储接口,因为我在配置Global属性时,已经说明了我要注入所有以 “I” 开头的接口,那么我就把这个用户的接口给定义为IUserRepository

当然,不同的实体类所需要的仓储接口也不一样,这里根据自己的实际需求去写需要的方法类,接口嘛,就不要在这里具体实现你的方法了

 public interface IUserRepository
    {
        Tuple<int,List<User>> GetList(User model);

        List<User> GetUserInfos();

        User GetSingle(User model);

        User GetbyID(int userID);

        void AddUser(User model);

        void ModifyUser(User model);

        void DeleteUser(User model);

        void SetUserInfoRole(int userID, List<int> roleIDList);

        List<AutoUserDo> GetUserInfobyName(string value);

        void ResetUserPWDbyID(int id);

    }

5.我们定义一个实现接口的类,然后把接口的方法给实现,这里面就是对数据实体进行操作了

public class UserRepository : IUserRepository
    { 

        public Tuple<int, List<User>> GetList(User model)
        {
            using (UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>())
            {
                var SysUserRepository = dal.GetRepository<User>();

                var conditions = ExpandHelper.True<User>();
                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And(a => a.UserName.Contains(model.UserName));

                if (!string.IsNullOrEmpty(model.UserReallyname))
                    conditions = conditions.And(a => a.UserReallyname.Contains(model.UserReallyname));

                if (model.DepartmentID > 0)
                    conditions = conditions.And(a => a.DepartmentID == model.DepartmentID);

                var templist = SysUserRepository.Get(filter: conditions, includeProperties: "RoleList");

                var count = templist.Count();

                if (model.order != null&&model.order.Count()>0)
                {
                    foreach (var item in model.order)
                    {
                        var column = model.columns.ElementAt(int.Parse(item.column));
                        templist = templist.OrderSort(column.data, item.dir);
                    }

                }
                var result = templist.PageBy(model.pageIndex, model.pageSize).ToList();

                return new Tuple<int, List<User>>(count, result);
            }
        }

        public User GetSingle(User model)
        {
            using(UnitOfWork dal=BaseInfo._container.Resolve<UnitOfWork>()){

                var conditions = ExpandHelper.True<User>();

                if (!string.IsNullOrEmpty(model.UserName))
                    conditions = conditions.And( a => a.UserName == model.UserName || a.MobilePhone == model.UserName);
                if (!string.IsNullOrEmpty(model.MobilePhone))
                    conditions = conditions.And(a => a.MobilePhone == model.MobilePhone);

                var result = dal.GetRepository<User>().Get(conditions).FirstOrDefault();
                return result;
            }
        }

        public User GetbyID(int userID)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

              //  var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID, includeProperties: "RoleList.MenuList,RoleList.rbList").AsNoTracking().FirstOrDefault();

                var result = dal.GetRepository<User>().Get(filter: a => a.UserID == userID,includeProperties: "RoleList").FirstOrDefault();

                foreach (var item in result.RoleList)
                {
                    var role=dal.GetRepository<Role>().Get(a=>a.RoleID==item.RoleID,includeProperties:"MenuList,rbList").FirstOrDefault();
                    item.MenuList = role.MenuList;
                    item.rbList = role.rbList;
                } 

                return result;
            }
        }

        public void AddUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                dal.GetRepository<User>().Insert(model);
                dal.Save();
            }
        }

        public void ModifyUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                dal.GetRepository<User>().UpdateSup(model, new List<string>() { "IsEnable", "CreateTime" }, false);
                dal.Save();
            }
        }

        public void DeleteUser(User model)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
               var sysUserRepository= dal.GetRepository<User>();
               var Usermodel = sysUserRepository.GetByID(model.UserID);
               Usermodel.IsEnable=Usermodel.IsEnable?false:true;
               sysUserRepository.UpdateSup(Usermodel, new List<string>() { "IsEnable" });
               dal.Save();
            }
        }

        /// <summary>
        /// 添加用户角色信息,先删除原有数据,在添加到数据库
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="roleIDList"></param>
        /// <returns></returns>
        public void SetUserInfoRole(int userID, List<int> roleIDList)
        {
            using (UnitOfWork dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                var sysUserRepository = dal.GetRepository<User>();
                var roleRepository = dal.GetRepository<Role>();
                var UserModel = GetbyID(userID);
                var roleList = UserModel.RoleList.ToList();

                roleList.ForEach(m =>
                {
                    var userModel = sysUserRepository.Get(filter: a => a.UserID == userID, includeProperties: "RoleList").FirstOrDefault();
                    var roleModel = roleRepository.GetByID(m.RoleID);
                    userModel.RoleList.Remove(roleModel);
                });

                roleIDList.ForEach(m =>
                {
                    var userModel = sysUserRepository.GetByID(userID);
                    var roleModel = roleRepository.GetByID(m);
                    userModel.RoleList.Add(roleModel);
                });

                dal.Save();
            }
        }

        public List<AutoUserDo> GetUserInfobyName(string value)
        {
            Mapper.Initialize(a =>
            {
                a.CreateMap<User, AutoUserDo>()
                 .ForMember(au => au.id, op => { op.MapFrom(user => user.UserID); })
                 .ForMember(au => au.text, op => { op.MapFrom(user => user.UserReallyname); })
                 .ForMember(au => au.department, op => { op.MapFrom(user => user.Department.DicValue); });
                a.CreateMap<Role, roleinfo>();
            });

            using (var dal = BaseInfo._container.Resolve<UnitOfWork>()) {

                return dal.GetRepository<User>()
                          .Get(a => a.UserReallyname.Contains(value) || a.MobilePhone == value, includeProperties: "Department,Role").ProjectToQueryable<AutoUserDo>().ToList();

            }
        }

        public void ResetUserPWDbyID(int id)
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {

                var repository = dal.GetRepository<User>();
                var usermodel = new User()
                {
                    UserID = id,
                    UserPassword = "123456"
                };
                repository.UpdateSup(usermodel, new List<string>() { "UserPassword" });
                dal.Save();
            }
        }

        public List<User> GetUserInfos()
        {
            using (var dal = BaseInfo._container.Resolve<UnitOfWork>())
            {
                return dal.GetRepository<User>().Get().ToList();
            }
        }
    }

6.然后我们就可以在MVC的控制器里面去调用这些方法来实现我们所想要的功能了,我这里只展示一个方法

public void SendEmailAsync(Message model)
        {
            Task.Run(() =>
            {
                try
                {
                    var reclist = string.Empty;
                    foreach (var item in model.RecUser.Split(','))
                    {
                        var userinfo = this.UserRepository.GetbyID(int.Parse(item));  //这里就调用了实现接口的那个类的方法,去验证用户的ID
                        if (!string.IsNullOrEmpty(userinfo.Email))
                        {
                            reclist += userinfo.Email + ",";
                        }
                    }
                    if (!string.IsNullOrEmpty(reclist))
                    {
                        reclist = reclist.Substring(0, reclist.Length - 1);
                        EmailHelper email = new EmailHelper(reclist, model.MessageTitle, model.MessageText);
                        email.Send();
                    }
                    model.SendEmailState = 2;
                    this.MessageServer.SetSendState(model);
                }catch(Exception ex){
                    new LogHelper().LogError("发送邮件异常" + ex);
                    model.SendEmailState = 3;
                    this.MessageServer.SetSendState(model);
                }
            });
        }

那么整个流程就是这样,看着别人写的那些博客里面的流程不是那么的全面,我这里就详细的把AutoFac的整个流程给梳理出来了,有不对的地方请及时指出

后面我会详细说明一下Unity IOC框架是如何使用的,这里我就不再叙述了

下面是两篇比较好的博文,我觉得比较有参考意义的,可以看一下,喜欢我发布的内容的可以关注我,后面还会有其他的干货和内容进行分享

.NET领域最为流行的IOC框架之一Autofac:https://www.cnblogs.com/yinrq/p/5381492.html

.NET Unity IOC框架使用实例:https://blog.csdn.net/chen_peng7/article/details/54896449

.NET领域最为流行的IOC框架之一Autofac WebAPI2使用Autofac实现IOC属性注入完美解决方案 AutoFac容器初步的更多相关文章

  1. WebAPI2使用Autofac实现IOC属性注入完美解决方案

    一.前言 只要你是.NETer你一定IOC,IOC里面你也会一定知道Autofac,上次说了在MVC5实现属性注入,今天实现在WebApi2实现属性注入,顺便说一下autofac的程序集的注入方式,都 ...

  2. .NET领域最为流行的IOC框架之一Autofac

    一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也是用的Autofac. Orchad和Nopcomm ...

  3. Spring 中IOC(控制反转)&& 通过SET方式为属性注入值 && Spring表达式

    ### 1. Spring IoC IoC:Inversion of control:控制反转:在传统开发模式下,对象的创建过程和管理过程都是由开发者通过Java程序来实现的,操作权在开发者的Java ...

  4. Java框架spring 学习笔记(六):属性注入

    属性注入:创建对象的时候,向类里面的属性设置值. Java属性注入有三种方法: 使用set方法注入 有参数构造注入 使用接口注入 Spring框架里面的属性注入方式 有参数构造属性注入 set方法属性 ...

  5. IOC框架之一Autofac

    .NET领域最为流行的IOC框架之一Autofac 一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程序也 ...

  6. .Net IOC框架入门之三 Autofac

    一.简介   Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个 目的 1.依赖注入的目的是为了解耦. 2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置. 3.控制反转即 ...

  7. .Net IOC框架入门之——Autofac

    一.简介  Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个 目的 1.依赖注入的目的是为了解耦.2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置.3.控制反转即IoC ...

  8. IOC框架的认识

    转:http://blog.csdn.net/wanghao72214/article/details/3969594 1 IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实 ...

  9. 轻量级IOC框架:Ninject

    Ninject 学习杂记 - liucy 时间2014-03-08 00:26:00 博客园-所有随笔区原文  http://www.cnblogs.com/liucy1898/p/3587455.h ...

随机推荐

  1. Java内存管理-掌握类加载器的核心源码和设计模式(六)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇文章介绍了类加载器分类以及类加载器的双亲委派模型,让我们能够从整体上对类加载器有 ...

  2. java8 Stream的实现原理 (从零开始实现一个stream流)

    1.Stream 流的介绍 1.1 java8 stream介绍 java8新增了stream流的特性,能够让用户以函数式的方式.更为简单的操纵集合等数据结构,并实现了用户无感知的并行计算. 1.2  ...

  3. Linux下 niginx部署

    部署nginx   一.新建文件夹,给放文件     conf 二.写入主页文件   三.复制配置文件   四.修改配置文件80           五.修改media  六. pkill -9 ng ...

  4. SpringBoot整合elasticsearch

    在这一篇文章开始之前,你需要先安装一个ElasticSearch,如果你是mac或者linux可以参考https://www.jianshu.com/p/e47b451375ea,如果是windows ...

  5. css3组件之几何图形

    一.平行四边形 1.实心无边框 #parallelogram { width: 150px; height: 100px; -webkit-transform: skew(20deg); -moz-t ...

  6. 最近公共祖先 LCA 倍增算法

          树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...

  7. React动画组件——React-Transitio-group动画实现

    React动画组件--React-Transitio-group动画实现 安装 项目目录下使用命令行 yarn add react-transition-group 安装组件.在需要使用动画的页面加入 ...

  8. Ubuntu 安装 Anaconda3 详细步骤

    主要介绍在 Ubuntu 14.04中安装 Anaconda3 的详细过程.(原文地址:http://blog.csdn.net/u012318074/article/details/77074665 ...

  9. 关于git的使用记录总结

    1.解决Windows下git换行符报警问题 git config --global core.autocrlf false 2.撤销add的文件退出暂存区 git reset --mixed 3.g ...

  10. JS引用类型之Array

    ECMAScript中的数组可以说是比较神奇了, ECMAScript中定义的数组每一项可以保存不同的数据类型,如第一项为字符串,第二项为数值等等 1. 那怎么创建一个数组呢? 方法和创建对象实例类似 ...