控制反转

在spring中我们使用applicationContext.xml文件来进行管理bean

就是将原本在程序中手动创建HelloService对象的控制权,交由Spring框架管理,简单说,就是创建HelloService对象控制权被反转到了Spring框架;

读取核心配置文件方式

ApplicationContext 应用上下文,加载Spring 框架配置文件

加载classpath:(这种方法常用)

     new ClassPathXmlApplicationContext("applicationContext.xml");

加载磁盘路径:

     new FileSystemXmlApplicationContext(磁盘路径+"applicationContext.xml");

三种实例化Bean的方式

1.使用类构造器实例化(默认无参数)(推荐)
<bean id=“personService" class=“com.jiyun.bean.impl.PersonServiceImpl"/>



2.使用静态工厂方法实例化(简单工厂模式) <bean id="personService" class="com..jiyun.factory.PersonServiceFactory" factory-method="createPersonService" /> public class PersonServiceFactory { public static PersonService createPersonService(){ return new PersonServiceImpl(); } }

3.使用实例工厂方法实例化(工厂方法模式): <bean id=“personServiceFactory" class="com.jiyun.factory.PersonServiceFactory"/> <bean id="personService" factory-bean=“personServiceFactory" factory-method="createPersonService" />


factory-method是你写的实体类中的

Bean的作用域

类别

说明

singleton

在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在

prototype

每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean()

request

每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境

session

同一个HTTP Session 共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext 环境

globalSession

一般用于Porlet应用环境,该作用域仅适用于WebApplicationContext 环境

 

singleton: 单例,默认spring 容器实例的bean为单例;

prototype:多例

Spring容器的生命周期

Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。

     <bean id=“foo” class=“...Foo” init-method=“setup” destory-method=“teardown”/>

当bean被载入到容器的时候调用setup    

当bean从容器中删除的时候调用teardown(scope= singleton有效)

依赖注入Bean的属性

构造函数注入

属性setter方法注入

接口注入

Spring支持前两种,依赖注入是单独的一种技术

<!-- 构造方法注入 -->
    <bean id="u1" class="com.jy.bean.User">
        <constructor-arg index="0" type="java.lang.Integer" value="10"/>
        <constructor-arg index="1" type="java.lang.String" value="王五"/>
    </bean> <!-- 构造方法注入 -->
    <bean id="u1" class="com.jy.bean.User">
        <constructor-arg index="0" type="java.lang.Integer" value="10"/>
        <constructor-arg index="1" type="java.lang.String" value="王五"/>
    </bean>


• 属性setter方法注入(推荐)

使用多个XML配置文件

方式一 :可以在创建ApplicationContext对象时传入多个配置文件

       ApplicationContext applicationContext = new

       ClassPathXmlApplicationContext("beans1.xml", "beans2.xml");

方式二 :可以在配置文件中通过<import>引入其他配置文件(推荐)

       <import resource="classpath:bean2.xml"/>

注解

javaSE:

方法重写@Override  校验子类重写父类的方法声明是否与父类完全相同;

注解基本作用:为了取代配置文件,实现零配置;

通过注解可以屏蔽配置文件内容过多,不易维护问题;

注解不能实现插拔功能:因为注解是写在java源码中的

使用注解定义Bean 类基本注解

除了@Component外,Spring提供了3个功能基本和@Component等效的注解

@Repository 用于对DAO持久层实现类进行标注

@Service 用于对Service服务层实现类进行标注

@Controller 用于对Controller控制层实现类进行标注

这三个注解是为了让标注类本身的用途清晰,Spring在后续版本会对其增强

 

//@Component(value="user")   //相等于<bean id="user" class="com.jy.bean.User"/>

//@Component   //如果不给类起名,默认使用的是类名首字母小写

@Component("user") //如果注解中只有一个属性值,可以不写属性名称

public class User {

       @Value(value="李四") //<property name="uname" value="张三"/>

       private String uname; //@Component(value="user")   //相等于<bean id="user" class="com.jy.bean.User"/>

自动装配Bean 属性级别注解

使用@Autowired 进行自动注入

@Service 标注业务类

@Repository 标注DAO

@Autowired 默认按照类型进行注入

如果存在两个相同Bean类型相同,则按照名称注入

@Autowired注入时可以针对成员变量或者setter方法

UserService.java

package com.zym.service;

import com.zym.dao.UserDaoInf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService  implements UserServiceInf{

    @Autowired
    private UserDaoInf daoInf;

    @Override
    public void selectUser() {
            daoInf.selectAll();
    }

}

UserDao.java

package com.zym.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao  implements UserDaoInf {

public void selectAll(){

    System.out.println("select all success");
}

}

测试

  @Test
    public void test1() {
        ClassPathXmlApplicationContext cpac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService ser= cpac.getBean("userService", UserService.class);//这个地方默认小写开头,
        ser.selectUser();
    }

通过名称注入

通过@Autowired的required属性,设置一定要找到匹配的Bean
使用@Qualifier指定注入Bean的名称
使用Qualifier 指定Bean名称后,注解Bean必须指定相同名称

@Resource

java本身带的

Spring提供对JSR-250中定义@Resource标准注解的支持

@Resource和@Autowired注解功能相似

Bean的初始化

User.java

@Component
public class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public User() {
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化");
    }

    @PreDestroy
    public void destory(){
        System.out.println("销毁");
    }

测试

    @Test
    public void test2() {
        ClassPathXmlApplicationContext a = new ClassPathXmlApplicationContext("applicationContext.xml");
//        Object user = a.getBean("user");
        a.close();

    }

相当于

Spring初始化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。
  <bean id=“foo” class=“...Foo” 
            init-method=“setup” 
            destory-method=“teardown”/>

Bean的作用域范围

@Scope注解用于指定Bean的作用范围

Bean的初始化(使用javaconfig来进行配置bean)

Spring3.0以JavaConfig为核心,提供使用Java类定义Bean信息的方法

@Configuration 指定POJO类为Spring提供Bean定义信息

@Bean 提供一个Bean定义信息

UserDaoInf.java

public interface UserDaoInf {

    public void selectAll();

}

UserDao.java

package com.zym.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDao  implements UserDaoInf {

public void selectAll(){

    System.out.println("select all success");
}

}

在跟你的dao层平级创建一个config,在下面创建如下文件

package com.zym.config;

import com.zym.dao.UserDao;
import com.zym.dao.UserDaoInf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserDaoConfig {
    @Bean
    public UserDaoInf getUserDao(){
        return new UserDao();
    }

    @Bean(name="getUserDao2xxx")
    public UserDaoInf getUserDao2(){
        return new UserDao();
    }


}

测试

 @Test
    public void test1() {
        ClassPathXmlApplicationContext cpac = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao xxx = cpac.getBean("getUserDao",UserDao.class);
        xxx.selectAll();
        }

代理模式

目的:为目标对象增强功能;

代码执行,为纵向执行 ,从上到下执行;

静态代理

主类

package com.jy.proxy;
//厂家 目标对象
public class Factory implements PublicInf{

    @Override
    public void computerList() {
        //介绍电脑
        System.out.println("电脑系列!!!");
        //买电脑福利
    }

}

代理类

package com.jy.proxy;

//代理对象 代理商
public class MyProxy implements PublicInf {
    private PublicInf inf;

    public MyProxy(PublicInf inf) {
        super();
        this.inf = inf;
    }

    // 代理的实现时调用厂家的功能
    @Override
    public void computerList() {
        //介绍电脑
        this.introduc();
        inf.computerList();
        //买电脑福利
        this.gift();
    }
    //介绍电脑
    public void introduc(){
        System.out.println("吹吹电脑有多牛!");
    }
    //买电脑福利
    public void gift(){
        System.out.println("免费送货。。。");
    }

}

接口规范类

package com.jy.proxy;
//目标对象和代理对象的公共功能
public interface PublicInf {
    //电脑系列
    public void computerList();
}

测试类

package com.jy.proxy;

public class Main {

    public static void main(String[] args) {
        // 从代理买电脑
        PublicInf inf = new Factory();
        MyProxy pro = new MyProxy(inf);
        pro.computerList();

    }

}

aop开发案例

beans.xml

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

    <!-- 配置业务 -->
    <bean id="target" class="com.zym.aop.BookBizImpl" />
    <!-- 日志方面 -->
    <bean id="log" class="com.zym.aop.LogAdvice" />
    <bean id="gift" class="com.zym.aop.GiftAdvice"/>

    <!-- 组装 -->
    <bean id="bookbiz" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces"><!-- 业务接口 -->
            <value>com.zym.aop.BookBizInf</value>
        </property>
        <property name="interceptorNames"><!-- 切面 -->
            <list>
                <value>log</value>
                <value>gift</value>
            </list>
        </property>
        <property name="target" ref="target"/><!-- 业务实现 -->
    </bean>

</beans>
BookBizInf.java
package com.zym.aop;

public interface BookBizInf {
    //买书
    public void buy(String uname, String bname, int price);
    //书评
    public void comment(String uname, String comments);
}
BookBizImpl.java
package com.zym.aop;
//业务逻辑,商业逻辑

public class BookBizImpl implements BookBizInf {
    // 买书
    public void buy(String uname, String bname, int price) {
        System.out.println("方法buy开始执行,");
        System.out.println("用户:"+uname+",买了一本:"+bname+",积分增加:"+price);
        System.out.println("方法buy执行结束。");
    }

    // 书评
    public void comment(String uname, String comments) {
        System.out.println("方法comment开始执行,");
        System.out.println("用户:"+uname+",发布书评:"+comments);
        System.out.println("方法comment执行结束。");
    }
}
GiftAdvice.java
package com.zym.aop;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.aop.AfterReturningAdvice;

//后置通知
public class GiftAdvice implements AfterReturningAdvice{

    @Override
    public void afterReturning(Object arg0, Method m, Object[] objs, Object arg3) throws Throwable {
        System.out.println("执行的方法为:"+m.getName()+",参数:"+Arrays.toString(objs)+",返现金为:¥88.00");
        
    }

}
LogAdvice.java
package com.zym.aop;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

import org.springframework.aop.MethodBeforeAdvice;
//前置通知
public class LogAdvice  implements MethodBeforeAdvice{

    @Override
    public void before(Method m, Object[] objs, Object arg2) throws Throwable {
        System.out.println("【日志】方法:"+m.getName()+",执行时间为:"+new Date()+",参数:"+Arrays.toString(objs));
        
    }

}

测试

package com.zym.aop;

import org.testng.annotations.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BookAopTest {

    @Test
    public void test() {
        //获得spring容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //获得代理对象
        BookBizInf bz = ac.getBean("bookbiz", BookBizInf.class);
        bz.buy("张三", "葫芦娃", 10);
        bz.comment("李四", "开发书真贵!");
    }

}

aop术语

  1. 连接点(Joinpoint)

       程序运行过程中,JVM负责程序运行。执行到某个方法时,JVM能识别当前执行的是哪个方法。这些定义在类中的方法,每个具有独立的功能,在AOP中,将这些具有特定功能的方法称为连接点

  1. 切入点(Pointcut)

       类中的方法具有很多,某些方法具有一些共同的流程,例如数据库连接的获取与关闭,事务的开启与提交,等等。将这些公共的特性抽取出来,抽取完毕后,原始方法中就缺少了这些被抽取的代码。在实际运行时,缺少这些代码是无法完成原始的功能的。这些被抽取了公共功能的方法称为切入点

       切入点一定是连接点,连接点不一定是切入点

       切入点指被抽取了共性功能的方法分

  1. 通知(Advice)

       切入点对应的方法的共性功能被抽取后,组成独立代码逻辑,被封装在某个类的某个方法中,在被抽取了共性功能的方法被执行时,这些代码逻辑还要加入原始方法的执行,这些被抽取出来组成独立代码逻辑的共性功能称为通知

  1. 引入(Introduction)

通知仅表示切入点被抽取的代码逻辑,对于切入点所在的类,如果存在有共性的成员变量或者成员方法,通知将无法进行描述。AOP提供引入机制,将共性功能的成员进行加入。

       引入机制可以为类添加额外的成员变量或者成员方法

       引入机制是在编译期或类加载期完成的

  1. 目标对象(Target Object)

被代理创建的对象,称为目标对象

  1. AOP代理(AOP Proxy)

切入点所在的类对象执行切入点方法时,需要将原始的共性功能(通知)加入,此时通过代理的形式创建类对象,并完成共性功能(通知)的加入,上述过程称为AOP代理

  1. 织入(Weaving)

通过AOP代理,完成了切入点与通知的融合,并组成了完整的代码逻辑,将通知加入到切入点对应位置的动作称为织入

  1. 切面(Aspect)

切面是一个设计概念,指切入点与通知的匹配模式,换句话说指被抽取了共性功能的方法(切入点)与被抽取的共性功能(通知)对应的绑定关系

execution

AOP切入点表达式支持多种形式的定义规则
execution:匹配方法的执行(常用)
    execution(public * *(..))
within:匹配包或子包中的方法(了解)
    within(com.jy.aop..*)
this:匹配实现接口的代理对象中的方法(了解)
    this(com.jy.aop.user.UserDAO)
target:匹配实现接口的目标对象中的方法(了解)
    target(com.jy.aop.user.UserDAO)
args:匹配参数格式符合标准的方法(了解)
    args(int,int)

匹配方法的执行(常用)
格式:execution(方法格式表达式)
例一:匹配所有指定返回值类型的方法
void *(..)    int *(..)        double *(..)
例二:匹配指定包或子包中类的方法
*..*()      com.jy.aop.user.dao.*.*(..)      cn..dao.*.*(..)
例三:匹配指定类或接口的方法
* *..UserImpl.*(..)       * *..*Impl.*(..)      * *..*DAO.*(..)
例四:匹配指定方法名或部分匹配方法名的方法
*..*.add(..)     *..*.*e*(..)     *..*.get*(..)
例五:匹配所有指定参数个数或类型的方法
* *..*.*(int,int)     * *..*.*(*,*) 

 



 

posted on 2019-07-08 19:35  睡觉的阿狸  阅读(165)  评论(0编辑  收藏  举报