1.AOP

1.1 什么是AOP

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方
式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

要理解切面编程,就需要先理解什么是切面。用刀把一个西瓜分成两瓣,切开的切口就是切面;炒菜,锅与炉子共同来完成炒菜,锅与炉子就是切面。web层级设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。

我们一般做活动的时候,一般对每一个接口都会做活动的有效性校验(是否开始、是否结束等等)、以及这个接口是不是需要用户登录。

按照正常的逻辑,我们可以这么做。

这有个问题就是,有多少接口,就要多少次代码copy。对于一个“懒人”,这是不可容忍的。好,提出一个公共方法,每个接口都来调用这个接口。这里有点切面的味道了。

同样有个问题,我虽然不用每次都copy代码了,但是,每个接口总得要调用这个方法吧。于是就有了切面的概念,我将方法注入到接口调用的某个地方(切点)。

同样有个问题,我虽然不用每次都copy代码了,但是,每个接口总得要调用这个方法吧。于是就有了切面的概念,我将方法注入到接口调用的某个地方(切点)。

这样接口只需要关心具体的业务,而不需要关注其他非该接口关注的逻辑或处理。
红框处,就是面向切面编程。

1.2 AOP能做什么

1.就是帮助我们减少重复代码的书写,从而提升可读性和开发效率

2.在不修改源码的情况下,对程序进行增强

3.AOP可以进行权限校验,日志记录,性能监控,事务控制

1.3 底层实现

AOP依赖于IOC来实现,在AOP中,使用一个代理类来包装目标类,在代理类中拦截目标类的方法执行并织入辅助功能。在Spring容器启动时,创建代理类bean替代目标类注册到IOC中,从而在应用代码中注入的目标类实例其实是目标类对应的代理类的实例,即使用AOP处理目标类生成的代理类。

代理机制:

Spring 的 AOP 的底层用到两种代理机制:

JDK 的动态代理 :针对实现了接口的类产生代理.

Cglib 的动态代理 :针对没有实现接口的类产生代理. 应用的是底层的字节码增强的技术 生成当前类的子类对象.

1.4 AOP相关术语

  • Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为

spring 只支持方法类型的连接点.

  • Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知.通知分为前置

通知,后置 通知,异常通知,最终通知,环绕通知(切面要完成的功能)

  • Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
  • Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行

期为类 动态地添加一些方法或 Field.

  • Target(目标对象): 代理的目标对象
  • Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程,spring 采用动态代理

织入,而 AspectJ 采用编译期织入和类装在期织入

  • Proxy(代理):一个类被 AOP 织入增强后,就产生一个结果代理类
  • Aspect(切面): 是切入点和通知(引介)的结合

1.5 AOP怎么用

1.动态代理

package com.tledu.dao.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class DynamicProxy implements InvocationHandler {private Object obj;public DynamicProxy(Object obj){this.obj = obj;}/*** @param proxy  代理的对象* @param method 代理的方法* @param args   方法的参数* @return 方法的返回值* @throws Throwable 异常*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//前置操作before(method);method.invoke(obj,args);//后置操作after(method);return null;}private void before(Method method) {System.out.println(method.getName()+" 开始调用");}private void after(Method method) {System.out.println(method.getName()+" 调用结束");}
}

测试

public static void main(String[] args) {UserDaoImpl userDao = new UserDaoImpl();/**第一个参数: 真实对象的类解析器第二个参数: 实现的接口数组第三个参数: 调用代理方法的时候,会将方法分配给该参数*/IUserDao iu = (IUserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),new DynamicProxy(userDao));User u = new User();u.setId(3);u.setName("aaa");iu.add(u);
}

newProxyInstance,方法有三个参数:

loader: 用哪个类加载器去加载代理对象

interfaces:动态代理类需要实现的接口

InvocationHandler: 传入要代理的对象创建一个代理,动态代理方法在执行时,会调用创建代理类里面的invoke方法去执行

注意:

JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。

2.注解方式

还是之前IOC的 再次引入三个就行,因为Spring的AOP是基于AspectJ开发的

在配置文件中引入AOP约束

<?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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd"><!-- 引入AOP约束 --><!-- 使用注解方式 --><context:annotation-config /><context:component-scan base-package="com.tledu" /><!-- 开启AOP的注解方式 --><aop:aspectj-autoproxy />
</beans>

通过注解的方式开启切面支持 @EnableAspectJAutoProxy

AOP类

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogInterceptor {@Pointcut("execution(public * com.tledu.service..*.add(..))")public void myMethod() {// 假设这个方法就是被代理的方法}@Before("myMethod()")public void beforeMethod() {System.out.println(" execute start");}@After("myMethod()")public void afterMethod() {System.out.println(" execute end");}// 环绕,之前和之后都有,相当于 @Before 和 @After 一起使用@Around("myMethod()")public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {// @Around也可以和@Before 和 @After 一起使用System.out.println("around start");// 调用被代理的方法pjp.proceed();System.out.println("around end");}
}

3. XML方式

引入jar包

和注解方式引入一样

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd"><context:annotation-config/><context:component-scan base-package="com.tledu"/><!--开启AOP注解--><!--<aop:aspectj-autoproxy />--><bean id="logInterceptor" class="com.tledu.aop.LogInterceptor"></bean><aop:config><aop:aspect id="logAspet" ref="logInterceptor"><!-- 需要进行代理的方法 --><aop:pointcut expression="execution(public * com.tledu.service..*.add(..))"id="pointcut" /><!-- 前后执行 --><aop:before method="beforeMethod" pointcut-ref="pointcut" /><!-- 或者这样写,这样就不需要pointcut标签了 --><!-- <aop:before method="before" pointcut="execution(public * com.tledu.service..*.add(..))"/> --><aop:after method="afterMethod" pointcut-ref="pointcut" /><!-- 环绕,一般要么使用 around 要和使用 before和after 不会一起使用 --><aop:around method="aroundMethod" pointcut-ref="pointcut" /></aop:aspect></aop:config></beans>

AOP类

和注解一样,但是把注解去掉

import org.aspectj.lang.ProceedingJoinPoint;
public class LogInterceptor {
public void myMethod() {// 假设这个方法就是被代理的方法
}
public void before() {System.out.println(" execute start");
}
public void after() {System.out.println(" execute end");
}
// 环绕,之前和之后都有,相当于 @Before 和 @After 一起使用
public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {// @Around也可以和@Before 和 @After 一起使用System.out.println("around start");// 调用被代理的方法pjp.proceed();System.out.println("around end");
}
}

测试类

public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = context.getBean(UserService.class);User u = new User();u.setName("李四");userService.add(u);
}

2.Spring中jdbcTemplate的使用

2.1 什么是jdbc Template

它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。

操作关系型数据的:

JdbcTemplate

HibernateTemplate

操作 nosql 数据库的:

RedisTemplate

操作消息队列的:

JmsTemplate

我们今天的主角在 spring-jdbc.jar 中,我们在导包的时候,除了要导入这个 jar 包 外,还需要导入一个 spring-tx.jar(它是和事务相关的>

2.2 jdbc Template对象的创建

我们可以参考它的源码,来一探究竟:

public JdbcTemplate() {
}
public JdbcTemplate(DataSource dataSource) {setDataSource(dataSource);afterPropertiesSet();
}
public JdbcTemplate(DataSource dataSource, boolean lazyInit) {setDataSource(dataSource);setLazyInit(lazyInit);afterPropertiesSet();
}

除了默认构造函数之外,都需要提供一个数据源。既然有set方法,依据我们之前学过的依赖注入,我们可以在配置文件中配置这些对象

2.3 配置数据源

1.环境搭建

2.配置文件引入约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>

3.配置DBCP数据源

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/ssm"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>

Spring 框架也提供了一个内置数据源,我们也可以使用 spring 的内置数据源,它就在spring-jdbc.jar中

 <!-- 配置数据源--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/ssm"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>

以上两种窦娥可以任选一种即可

2.4 增删改查

1.配置jdbc Template

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置一个数据库的操作模板:JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property>
</bean><!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/ssm"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>
</beans>

2. 基本用法

public static void main(String[] args) {DriverManagerDataSource ds = new DriverManagerDataSource();ds.setDriverClassName("com.mysql.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/ssm");ds.setUsername("root");ds.setPassword("root");//1.创建JdbcTemplate对象JdbcTemplate jt = new JdbcTemplate();//给jt设置数据源jt.setDataSource(ds);//2.执行操作jt.execute("insert into t_user(username,password)values('ccc','aaa')");}

3. Spring整合后的基本用法

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jt = (JdbcTemplate) context.getBean("jdbcTemplate");
//jdbcTemplate.execute("insert into t_user(username,password)values('张美玲','888')");
// 查询所有
List<User> accounts = jt.query("select * from t_user",new UserRowMapper());
for (User account : accounts) {System.out.println(account);
}
System.out.println("--------");
User user = jt.queryForObject("select * from t_user where id = ?",new BeanPropertyRowMapper<User>(User.class),1);
System.out.println(user);System.out.println("--------");
//返id大于3的总条数
Integer count  = jt.queryForObject("select count(*) from t_user where id > ?", Integer.class, 3);
System.out.println(count);
//多条件查询 、模糊查询
List<User> ulist = jt.query("select * from t_user where t_user.username like ? and nickname like ? ",new UserRowMapper(),new Object[]{"%a%","%a%"});
System.out.println(ulist.size());
for (User user1 : ulist) {System.out.println(user1);
}

定义User的封装策略

public class UserRowMapper implements RowMapper<User> {@Overridepublic User mapRow(ResultSet rs, int i) throws SQLException {User u = new User();u.setId(rs.getInt("id"));u.setUsername(rs.getString("username"));return u;}
}

2.5 Dao层中添加jdbc Template

1. 实体类

public class User {private Integer id;private String username;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +'}';}
}

2. 定义IUserDao接口

public interface IUserDao {//添加一条用户信息void add(User user);//根据id删除一条数据void delete(Integer id);//修改一条数据void update(User user);//根据条件查询用户信息列表List<User> getUserList(User user);//根据id查询一条数据User getUserById(Integer id);//获取总条数Integer getListCount();
}

3. 在UserDaoImpl实现类中添加jdbcTemplate

public class UserDaoImpl implements IUserDao {private JdbcTemplate jdbcTemplate;@Overridepublic void add(User user) {String sql = " insert into t_user(username) values('"+user.getUsername()+"') ";jdbcTemplate.execute(sql);}@Overridepublic void delete(Integer id) {String sql = "delete from t_user where id = "+id+"";jdbcTemplate.execute(sql);}@Overridepublic void update(User user) {String sql = "update t_user set username = '"+user.getUsername()+"' where id = "+user.getId()+"";jdbcTemplate.execute(sql);}@Overridepublic List<User> getUserList(User user) {String sql = " select * from t_user where 1=1 ";if(user.getUsername()!=null){sql += "and username like '%"+user.getUsername()+"%'";}return jdbcTemplate.query(sql,new UserRowMapper());}@Overridepublic User getUserById(Integer id) {String sql = " select * from t_user where id = "+id+" ";return jdbcTemplate.queryForObject(sql,new UserRowMapper());}@Overridepublic Integer getListCount() {String sql = "select count(*) from t_user where username like '%美%'";return jdbcTemplate.queryForObject(sql,Integer.class);}public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}
}

4. 在配置文件中给UserDaoImpl注入jdbcTemplate

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置账户的持久层 -->
<bean id="accountDao" class="com.tledu.dao.impl.UserDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean><!-- 配置一个数据库的操作模板:JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property>
</bean><!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/ssm"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>
</beans>

5. 测试

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jt = (JdbcTemplate) context.getBean("jdbcTemplate");
//jdbcTemplate.execute("insert into t_user(username,password)values('张美玲','888')");
// 查询所有
List<User> accounts = jt.query("select * from t_user",new UserRowMapper());
for (User account : accounts) {System.out.println(account);
}
System.out.println("--------");
//根据id查询一条数据
User user = jt.queryForObject("select * from t_user where id = ?",new BeanPropertyRowMapper<User>(User.class),1);
System.out.println(user);System.out.println("--------");
//返id大于3的总条数
Integer count  = jt.queryForObject("select count(*) from t_user where id > ?", Integer.class, 3);
System.out.println(count);
//多条件查询 、模糊查询
List<User> ulist = jt.query("select * from t_user where t_user.username like ? and nickname like ? ",new UserRowMapper(),new Object[]{"%a%","%a%"});
System.out.println(ulist.size());
for (User user1 : ulist) {System.out.println(user1);
}

6. 问题

此种方式有什么问题吗?

答案:

有个小问题。就是我们的 dao 有很多时,每个 dao 都有一些重复性的代码。下面就是重复代码:

private JdbcTemplate jdbcTemplate;

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

this.jdbcTemplate = jdbcTemplate;

}

7. 继承JdbcDaoSupport

JdbcDaoSupport 是 spring 框架为我们提供的一个类,该类中定义了一个 JdbcTemplate 对象,我们可以直接获取使用,但是要想创建该对象,需要为其提供一个数据源:

具体源码如下:

public abstract class JdbcDaoSupport extends DaoSupport {
//定义对象
private JdbcTemplate jdbcTemplate;
//set 方法注入数据源,判断是否注入了,注入了就创建 JdbcTemplate
public final void setDataSource(DataSource dataSource) {if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {//如果提供了数据源就创建 JdbcTemplatethis.jdbcTemplate = createJdbcTemplate(dataSource);initTemplateConfig();}
}
//使用数据源创建 JdcbTemplate
protected JdbcTemplate createJdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);
}
//当然,我们也可以通过注入 JdbcTemplate 对象
public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;initTemplateConfig();
}
//使用 getJdbcTmeplate 方法获取操作模板对象
public final JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}

8. UserDaoImpl实现类继承JdbcDaoSupport

public class UserDaoImpl2 extends JdbcDaoSupport implements IUserDao {//private JdbcTemplate jdbcTemplate;@Overridepublic void add(User user) {String sql = " insert into t_user(username) values('"+user.getUsername()+"') ";super.getJdbcTemplate().execute(sql);}@Overridepublic void delete(Integer id) {String sql = "delete from t_user where id = "+id+"";super.getJdbcTemplate().execute(sql);}

9. 在applicationContext.xml中给UserDaoImpl注入dataSource

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/ssm"></property><property name="username" value="root"></property><property name="password" value="root"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userDao" class="com.tledu.dao.impl.UserDaoImpl2"><!--<property name="jdbcTemplate" ref="jdbcTemplate"></property>--><property name="dataSource" ref="dataSource"></property>
</bean>

10. 测试

public class UserDaoImplTest2 {private ApplicationContext context;@Beforepublic void before(){context = new ClassPathXmlApplicationContext("applicationContext.xml");}@Testpublic void add(){IUserDao userDao = context.getBean(UserDaoImpl2.class);User user = new User();user.setUsername("乔森");userDao.add(user);}@Testpublic void delete(){IUserDao userDao = context.getBean(UserDaoImpl2.class);userDao.delete(26);}

Spring 学习 day3 : AOP,Spring中JdbcTemplate的使用相关推荐

  1. Spring 学习二-----AOP的原理与简单实践

    一.Spring  AOP的原理 AOP全名Aspect-Oriented Programming,中文直译为面向切面(方面)编程.何为切面,就比如说我们系统中的权限管理,日志,事务等我们都可以将其看 ...

  2. Spring学习笔记 之 Spring<全>

    开始学习Spring全家桶 文章目录 1. IoC 定义 为什么叫控制反转? 实现 IoC 容器创建 bean 的两种⽅式 IoC DI 特殊字符的处理 Spring 中的bean创建类型 -- sc ...

  3. spring学习笔记(spring概述和IOC)

    spring5 1.spring的概述 1.1.spring是什么 Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发的复杂性而创建的. Spring 的 ...

  4. [spring学习] 1、spring下载与使用

    目录 spring介绍 spring核心部分 spring的下载 idea使用spring 总结 spring介绍 Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Jo ...

  5. Spring 学习之 二----Spring创建对象的三种方式

    最近在系统的学习Spring,现在就Spring的一些知识进行总结. 我们知道Spring是一个开放源代码的设计层面的框架,他主要解决的是业务逻辑层与其他各层之间松耦合的问题. Spring 有三个核 ...

  6. Spring学习笔记之Spring Web Flow

    Spring Web Flow 是Spring MVC 的扩展,它支持开发基于流程的应用程序.它将流程的定义与实现流程行为的类和视图分离开来. 1.配置Web Flow 在Spring MVC上下文定 ...

  7. Spring学习之AOP(面向切面编程)

    动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...

  8. Spring学习之AOP

    Spring-AOP(Aspect-orented programming) 在业务流程中插入与业务无关的逻辑,这样的逻辑称为Cross-cutting concerns,将Crossing-cutt ...

  9. 【Spring学习】AOP实现日志记录

    AOP知识点 AOP,面向切面编程.通过预编译方式和运行时动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. AOP编程思想就是把很多类对象中的横切问题点,从业务逻辑中分离出来,减少 ...

最新文章

  1. 【Go】Go基础(五):函数
  2. HDU 1285 - 确定比赛名次(拓扑排序)
  3. 51nod1258 序列求和 V4(伯努利数+多项式求逆)
  4. if函数如何嵌入多个android,Android中多个EditText输入效果的解决方式
  5. 后端需要掌握的技术_何小伟:软件测试需要掌握的技术?
  6. lisp代码编写地物符号_Aroma:通过结构代码搜索推荐代码
  7. Eclipse常用插件之Top10
  8. linux安装思源字体下载,fedora25安装字体-以思源字体为例 适合中文用户
  9. book_note for《Linux程序设计》chapter3 Linux系统C语言开发工具
  10. linux 提示libaio.so.1,解决Mysql报错缺少libaio.so.1
  11. 【C语言】的%*d、%.*s等详解:
  12. 最快下载速度100Mbps!4G LTE技术全解析
  13. mysql比较两个表数据的差异_mysql实用技巧之比较两个表是否有不同数据的方法分析...
  14. flv怎么转换成html5,快速教你如何将FLV转换MP4格式
  15. python开发bi报表_BI报表有什么优势
  16. 11.3-11.4kmp专题训练
  17. 怎么关闭计算机右侧的硬盘预览,选择性关闭视频文件预览 给Win7硬盘CPU减压
  18. 积分电路和微分电路的特点
  19. 仓库管理(库存系统模块)
  20. Android写一个简易计算器(可以实现连续计算)

热门文章

  1. 央企:华润电力2023秋季校园招聘
  2. 加密与安全——数字证书
  3. 基于canny边缘检测、形态学、区域统计实现MATLAB的纽扣计数
  4. 20230107英语学习
  5. c++[ZJOI2011]看电影
  6. Zabbix端口监控
  7. 智能门锁指纹锁方案——西城微科
  8. VS无法查找或打开 PDB 文件
  9. 华丽成长为IT高富帅、IT白富美(十一)
  10. Gradle获取当前编译的Flavor