mysql 1 -- 基础语法、函数、联表查询、事务

spring介绍

1.解耦

耦合就是指代码之间的依赖性。解耦就是尽可能的降低代码之间的依赖性。

class1 = new Class2(),那么class1就和class2耦合了,如果class2没有的话,那么class1就会出现编译错误(ERROR,而不是异常Exception),所以可以用映射文件的办法,来解耦。

减少耦合性,就是少用new

2.解耦常用的一种方法是:利用映射文件来进行创建新对象。

配置文件中,后面要写全类限定名。而且写的是实现类。

image.png

映射法需要用到配置文件。以后不再有各种各样复杂的配置,而是通过配置文件来进行修改。只使用字符串,而不使用真实的类名。

image.png

3.javaBean和properties对象的创建,尤其是spring Resource,见下图。
4.引入工厂模式,所需要的对象直接从工厂里面拿。这是ioc核心。

ioc全名叫做反转控制,为什么这么叫?因为如果有类使用工厂模式,相当于把他自己创建新对象的权利交给了BeanFactory,那么就称为把权利反转给BeanFactory,由BeanFactory进行控制。

比如后图2.

如图所示,Client把自己new一个对象的权利交给beanFactory。

/**
 * 仿照  BeanFactory 创建一个自己的
 */

public class MyFactory {

    private static Properties prop;
    private static Map<String, Object> map;
    static {
        try {
            prop = new Properties();
            map = new HashMap<>();
            InputStream is = MyFactory.class.getClassLoader().getResourceAsStream("application.properties");
            prop.load(is);
            Enumeration<Object> keys = prop.keys();
            while(keys.hasMoreElements()) {
                String key = keys.nextElement().toString();
                Object o = Class.forName(prop.getProperty(key)).newInstance();
                map.put(key,o);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public Object getBean(String name) {
        return map.get(name);
    }
}

image.png

5.总结一句话:ioc(控制反转)作用就是为了解耦。

二、spring项目的创建

1.把bean交给spring管理。怎么交?

在resource下创建bean.xml文件。然后引入约束,进行bean配置(创建对象的映射。)

<?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">
    <!--第一步配置xml约束和 beans约束-->
    <!--第二步,配置对象映射文件  id和class-->
    <bean id="AccountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
    <bean id="AccountService"class="com.itheima.service.impl.AccountServiceImpl"></bean>
</beans>

image.png

2.第二步:获取容器对象,得到配置文件中的内容。怎么获取?

用ApplicationContext对象。

image.png

ApplicationContext是一个接口,常用的实现类有三种。

1.)AnnontationConfigApplicationContext

2.)FileSystemXmlApplicationContext

3.)ClassPathXmlApplicationContext

image.png

BeanFactory和ApplicationContext:一个延迟加载创建多例对象。另一个立即加载产生单例对象

3.核心容器接口有很多,包括BeanFactory和ApplicationContext,怎么确定选择哪一个呢?

image.png

三、依赖注入:普通无参注入,有参注入(此又分构造注入、传值注入)
1.普通无参构造方法注入

image.png

2.有参方法注入,分两种(构造注入,传值注入)
下图是构造注入

image.png

image.png

还有一种是传值注入
1.被注入的类中要写set方法
2.配置文件中使用property

image.pngimage.png

四、几种表达式
${ } 是jsp中 EL标签的最常用表达

image.png

OGNL标签是直接使用

下图:s:property是struts的标签。
value后面的值是 OGNL表达式。

注意OGNL如果取类怎么取?取类中的静态方法呢?加@

image.png

单例,多例

scope作用范围

init-method

destroy-mothod

复杂类型的注入list,map等

分模块开发

第二天

使用注解方式的步骤

在service中写注解(比如@Component等)–>在配置文件中写context

1.注解

1)Component,Service,Repository注解:

image.png

image.png

2)Autowired,Qualifier,Resource,Value

image.png

使用set方法是怎样的?(类中写set,配置中写property)

image.pngimage.pngimage.png

Autowired+private行中的
accountDao = Autowired+Qualifier=resource

image.pngimage.png

3)Scope,PreDestory,PostConstruct
image.png

303.ApplicationContext是一个接口,常用的实现类有三种。(了解)

1.)AnnontationConfigApplicationContext

2.)FileSystemXmlApplicationContext

3.)ClassPathXmlApplicationContext

304.根据context中的id获取对象(了解)

// 从容器里取值的时候有两种方法,一种强制转换,一种是在第二个参数位置,显示声明

// Student student1 = context.getBean("student",Student.class);

Student student = (Student) context.getBean("student2");

305. bean中属性的含义:id,class,name,scope(了解)

id:相当于对象名

class:对象所对应的全限定名

name:相当于别名,而且可以取多个,可以通过 逗号, 分号; 或 空格分开

scope:singleton(单例) prototype(多例)

306. 有参构造方法有三种方式(了解)

第一种:通过属性名

  <bean id="hello" class="demo.pojo.Hello" name="ss,ee" scope="prototype"><constructor-arg name="str" value="1:通过属性的名字"/>

  </bean>

第二种:通过属性类型(不常用)

  <bean id="hello" class="demo.pojo.Hello" autowire=”byName / byType”>

​    <constructor-arg type="java.lang.String" value="2:通过属性的类型"/>

  </bean>

第三种:通过索引

  <bean id="hello" class="demo.pojo.Hello"><constructor-arg index="0" value="3:通过索引"/>

</bean>

307.设置别名 (了解)

通过import导入其他的配置文件

指定要扫描的包 <context:component-scan base-package=“demo.model” />

bean属性autowire:byName:通过名字去查找,自动注入;byType:通过class去查。

p命名空间和c命名空间(p:property;c:constructor):
<bean id="student2" class="demo.pojo.Student" c:name="李四" 
      c:wife="gg" p:name="张三" p:wife="ss"/>

**
**

308.丰富类型赋值(了解)

空是 数组是 map是

list是 配置是value set是

    <!-- String-->
    <property name="wife">
        <null/>
    </property>
    <!-- 配置-->
    <property name="info">
        <props>
            <prop key="driver">demo.pojo.Student</prop>
        </props>
    </property>
    <!-- 数组注入-->
    <property name="books">
        <array>
            <value>红楼梦</value>
        </array>
    </property>
    <!-- List注入-->
    <property name="bobbys">
        <list>
            <value>打代码</value>
        </list>
    </property>
    <!-- map注入-->
    <property name="card">
        <map>
            <entry key="身份证" value="1222"/>
        </map>
    </property>
    <!-- Set-->
    <property name="games">
        <set>
            <value>LOL</value>
        </set>
    </property>

上面都是一些xml文件的配置

怎么配置bean,如果有很多配置文件怎么导入,set,map,property这些特殊类型怎么赋值,有参构造方法怎么赋值,怎么扫描包,怎么设置别名,怎么取值

但是以后最常用的还是注解方式

**309.**以上各种问题怎么用注解解决?(了解)

@Scope(“singleton”) property对应的是 @Value(“kuangshen”) public String name;

@ComponentScan(basePackages = {“aop.anno”})

@Component @Repository @Service @Controller

@Autowire是通过byType的,如果有很多的话(比如一个接口有多个实现类),还要通过@Qualifier再通过名字找一次

@Resource是先通过byName去找,如果找不到,会自动通过byType再找一次。

@Nullable字段标记了这个注解,说明这个字段可以是null

下面进入AOP的学习

310.静态代理。

类如下:Service接口(add del等方法) ServiceImpl(Service的实现类。真实类)

ServiceProxy类(代理类)实现了Service接口,接受实现类作为参数

public class ServiceProxy implements Service {
    private Service service;
    public void log(String msg) { System.out.println("方法名是:"+msg); }
    public void setService(Service service) { this.service = service; }
    public void del() { log("del");  service.del(); }
    public void add() { log("add");  service.add(); }
}

具体流程:代理类实现了真实类实现的接口。 代理类接受真实类作为参数。

代理类对接口里的方法进行加工(比如运行前打印下日志。或者对参数进行一些变动)

具体看下面(Service是接口。 ServiceImpl是真实类。 ServiceProxy是代理类)

public interface Service {
    void del();
    void add();
    void update();
    void query();
}
public class ServiceImpl implements Service {
    public void del() {
        System.out.println("del执行了。");
    }
    public void add() {
        System.out.println("add执行了。");
    }
    public void update() {
        System.out.println("update执行了。");
    }
    public void query() {
        System.out.println("query执行了。");
    }
}
public class ServiceProxy implements Service {
    private Service service;
    //这里对具体的方法进行日志输出,然后再调用真实方法
    public void log(String msg) {
        System.out.println("方法名是:" + msg);
    }
    //接受真实类作为参数
    public void setService(Service service) {
        this.service = service;
    }
    public void del() {
        log("del");
        service.del();
    }
    public void add() {
        log("add");
        service.add();
    }
    public void update() {
        log("update");
        service.update();
    }
    public void query() {
        log("query");
        service.query();
    }
}
public class Client {
    public static void main(String[] args) {
          //先创建真实角色
        ServiceImpl impl = new ServiceImpl();
          //创建代理角色
        ServiceProxy proxy = new ServiceProxy();
          //把真实角色给代理角色
        proxy.setService(impl);
          //通过代理角色调用方法
        proxy.add();
    }
}

311.动态代理:即代理类不是我们写的,而是动态生成的

动态代理分成两大类:

基于接口–JDK动态代理(创建实现类代理对象,增强类的方法)

基于类:CGLIB(创建子类的代理对象,增强类的方法)

jdk动态代理

首先是一个程序:调用处理程序。 所属:代理类的实例。

作用,接受真实角色(setTarget),创建代理类实例(代理角色)(return new Proxy.new),

处理代理角色接管的真实角色的方法,并且可以加上代理角色自己的方法。

/**
 * 1.ClassLoad为什么用的是这个类的ClassLoad?JDKProxy是什么?
 * 2.上一个用的是MyInvocationHandler的ClassLoad
 * MyInvocationHandler是 调用处理程序 (实现了InvocationHandler接口)
 * 3.invoke方法什么时候被调用的?怎么被调用的?整个动态代理的实现流程是什么?
 * Proxy.newnewProxyInstance(ClassLoad,行为接口的class,调用处理程序) ->
 * 给第3参数传真实角色 —>第3参数调用invoke()实现增强。
 */
public class JDKProxy {
    public static void main(String[] args) {
        Class<UserDAO>[] interfaces = new Class[]{UserDAO.class};
        //        先生成代理类,通过代理类执行方法
        //        三个参数:当前类的ClassLoader; 要被代理的接口(要字节码形式的); 调用处理程序;
        UserDAO userDAO = new UserDAOImpl();
        UserDAO proxy = (UserDAO) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new MyInvoHanlder(userDAO));
        int add = proxy.add(1, 2);
        proxy.update("d");
        System.out.println(add);
    }
}

class MyInvoHanlder implements InvocationHandler {
    private Object obj;

    //    调用 调用处理程序 的时候必须给定 真实角色(就是接口的实现类)
    public MyInvoHanlder(Object obj) {
        this.obj = obj;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法执行之前:方法的名字是 ‘add’。  给方法传递的参数是:‘[1, 2]’
        System.out.println("方法执行之前:方法的名字是 ‘" + method.getName() + "’。  给方法传递的参数是:‘" + Arrays.toString(args) + "’");
        Object returnValue = method.invoke(obj, args);  //returnValue=null
        System.out.println("方法执行之后。。" + returnValue);
        return returnValue;
    }
}

说明:AOP是属于代理模式的,他们都是面向切面编程。

代理模式是嵌入到每个方法内部的。(比如一个UserService接口里有add,del,update方法,那么这些方法里面都需要添加一个打印语句。就可以通过代理模式实现。代理角色自己有一个log方法,并且给每个真实方法里加上这个log方法。)

基于类:CGLIB
//这里是动态代理机制:即代理类不是我们写的,而是动态生成的
//这是 代理实例的  调用处理程序(是一个程序,属于代理实例)
public class MyInvocationHandler implements InvocationHandler {
    //    被代理的接口
    private Object target;

    public void setRent(Rent rent) {
        this.target = rent;
    }

    //    生成代理类
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    //    处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        动态代理的本质,就是使用反射机制实现
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg) {
        System.out.println("方法" + msg + "执行了");
    }
}

312.AOP重点名词辨析

被增强类的所有方法都是连接点,其中真正被增强的方法称为切入点

增强类的增强方法被称为通知。 通知根据时期分为多种:前置通知、后期通知、返回通知、环绕通知、异常通知

切面:是动作,或者说一个过程。没有具体意义

代理:生成的代理对象**
**

1、连接点(JointPoint) 类里面哪些方法可以被增强,这些方法称为连接点

2、切入点(PointCut) 实际被真正增强的方法,称为切入点

3、通知(Advice,增强方法):

(1)实际增强的逻辑部分称为通知(增强)

(2)通知有多钟类型:前置通知(Before) 后置通知(AfterReturning也叫返回通知)

环绕通知(Around) 异常通知(AfterThrowing) 最终通知

4、切面(Aspect) 是动作,把通知应用到切入点的过程

5、代理(Proxy):目标对象应用通知之后创建的对象

313.AOP应用实例

纯注解版:

使用aop的流程

  1. 创建需要被增强的类(比如User)
  2. 创建增强类(比如UserProxy)
  3. 创建配置文件,开启注解扫描(比如在ProxyConfig上加上@ComponentScan)
  4. 配置注解,确定前置后置,环绕等(在UserProxy类里添加 @Before、@After方法)

增强类和被增强类 都加Component,归spring管理

给增强类增加 Aspect — 生成代理类(比如给UserProxy加上@Aspect)

开启Aspect自动生成代理对象(比如给ProxyConfig加上@EnableAspectJAutoProxy)

  1. 配置不同的通知类型 后面的值是切入点表达式:表示出切入点的位置(就是对那个类的那个方法进行增强)
@Component
public class User {
    public void addUser() {
        System.out.println("add.........");
        // int i = 5/0;
    }
}
/**
 * around在before之前,在after之后
 *
 * after是防止执行完,return之前执行,afterReturning是执行return之后才调用
 * 所以后者早于前者
 *
 * 如果出现异常,after执行,afterReturning和around后面都不执行
 */
@Component
@Aspect
public class UserProxy {
    //相同切入点抽取
    @Pointcut("execution(* aop2.*.*(..))")
    public void pointDemo() {    }

    // execution(权限修饰符、返回类型[可省略]、全类名.方法名(参数列表))
    @Before("execution(* aop2.User.addUser(..))")
    public void before() {
        System.out.println("before.......");
    }

    @After("execution(* *.*.*(..))")
    public void after() {
        System.out.println("after........");
    }

    @AfterReturning("execution(* aop2.*.*(..))")
    public void afterReturning() {
        System.out.println("afterReturning.....");
    }

    @Around("pointDemo()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around之前.....");
        proceedingJoinPoint.proceed();
        System.out.println("around之后.......");
    }

    @AfterThrowing("pointDemo()")
    public void afterThrowing() {
        System.out.println("afterThrowing........");
    }
}
@Component
@EnableAspectJAutoProxy
public class AopConfig {
}
public class TestAop {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("aop2");
        User user = context.getBean("user", User.class);
        user.addUser();
    }
}
没开 5/0的运行结果: after在return之前。 afterReturning在return之后。所以 afterReturning肯定在return之前。around两个之前。 before之前,after之前

image.png

开始5/0之后:before、after不受影响。 around和afterReturning都不执行

image.png

也可以不用注解实现,用纯xml实现

也分两种办法

增强类实现通知,然后xml只配置切入点和通知的ref
//method:要执行的目标对象的方法   args:参数   target:目标对象
public class BeforeLog implements MethodBeforeAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    //    returnValue:返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + method.getName() + "方法,返回结果为:" + returnValue);
    }
}

xml配置

<bean id="beforeLog" class="aop.model.BeforeLog"/>
<bean id="afterLog" class="aop.model.AfterLog"/>

    <!--配置aop-->
<aop:config>
        <!--切入点:expression:表达式,execution(要执行的位置)-->
    <aop:pointcut id="pointcut" expression="execution(* aop.service.UserServiceImpl.*(..))"/>
    <aop:pointcut id="pointcut1" expression="execution(* aop.service.UserServiceImpl.*(..))"/>
        <!--执行环绕通知-->
    <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut1"/>
</aop:config>

第二种方法

增强类不实现增强方法

<!--配置aop增强-->
<aop:config>
  <!--切入点-->
  <aop:pointcut id="p" expression="execution(* aop.anno.*.*(..))"/>
  <!--配置切面-->
  <aop:aspect ref="recordProxy">
    <!--增强作用在具体的方法上-->
    <aop:after method="after" pointcut-ref="p"/>
  </aop:aspect>
</aop:config>

注意:切面的ref必须是recordProxy(增强类)

method必须是切面的ref联系的类里面的方法。 pointcut-ref连接的是切入点。(切入点表达式说明了切点所在的位置。)

注意:无论是@Aspect还是<aop:aspect ref>都是作用在增强类上的。@Before,@Pointcut也都是作用在增强类内部的方法上。

ion="execution(* aop.service.UserServiceImpl.*(..))"/>
        <!--执行环绕通知-->
    <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut1"/>
</aop:config>

第二种方法

增强类不实现增强方法

<!--配置aop增强-->
<aop:config>
  <!--切入点-->
  <aop:pointcut id="p" expression="execution(* aop.anno.*.*(..))"/>
  <!--配置切面-->
  <aop:aspect ref="recordProxy">
    <!--增强作用在具体的方法上-->
    <aop:after method="after" pointcut-ref="p"/>
  </aop:aspect>
</aop:config>

注意:切面的ref必须是recordProxy(增强类)

method必须是切面的ref联系的类里面的方法。 pointcut-ref连接的是切入点。(切入点表达式说明了切点所在的位置。)

注意:无论是@Aspect还是<aop:aspect ref>都是作用在增强类上的。@Before,@Pointcut也都是作用在增强类内部的方法上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值