Spring

1.控制反转

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
在这里插入图片描述

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 //getBean : 参数即为spring配置文件中bean的id .
    Hello hello = (Hello) context.getBean("hello");
    Hello hello = context.getBean("hello",Hello.class);

控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
反转 : 程序本身不创建对象 , 而变成被动的接收对象 .

2.依赖注入

依赖注入 : 就是利用set方法来进行注入的.要求被注入的属性 , 必须有set方法

依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .

<bean id="OracleImpl" class="com.thebs.pojo.UserDaoOracleImpl"/>
    <bean id="userDao" class="com.thebs.service.UserServiceImpl">
        <!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
        <!--引用另外一个bean , 不是用value 而是用 ref-->
        <property name="userDao" ref="OracleImpl"></property>
    </bean>

常量注入、Bean注入、数组注入、List注入、Map注入

常量:<property name="name" value="小明"/>
bean:<property name="address" ref="addr"/>
数组、List、Set:类似

<property name="books">
        <array>
            <value>西游记</value>
            <value>红楼梦</value>
            <value>水浒传</value>
        </array>
    </property>

Map:

<property name="card">
    <map>
        <entry key="中国邮政" value="456456456465456"/>
        <entry key="建设" value="1456682255511"/>
    </map>
</property>

Null注入:<property name="wife"><null/></property>
Properties注入:

<property name="info">
    <props>
        <prop key="学号">20190604</prop>
        <prop key="性别"></prop>
        <prop key="姓名">小明</prop>
    </props>
</property>

拓展注入方式

①P命名空间注入 : 需要在头文件中假如约束文件
xmlns:p="http://www.springframework.org/schema/p"
可以直接注入属性的值
<bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>
②C命名空间注入 : 需要在头文件中假如约束文件
xmlns:c="http://www.springframework.org/schema/c"
注入构造器参数
<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>

3.创建对象的方式

在执行getBean的时候, user已经创建好了

有参时的bean配置
①通过下标:
<constructor-arg index="0" value="kuangshen2"/>
②通过参数名:
<constructor-arg name="name" value="kuangshen2"/>
③通过参数类型:
<constructor-arg type="java.lang.String" value="kuangshen2"/>

4.Bean的配置

id 是bean的标识符,要唯一
name可以设置多个,用逗号,分号,空格隔开
不配置id和name时,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名

<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
    <property name="name" value="Spring"/>
</bean>

5.作用域

在这里插入图片描述
singleton:单例,默认
<bean name="hello" class="com.thebs.pojo.Hello" scope="singleton">
prototype:原型模式,每次从容器取都产生新对象
<bean name="hello" class="com.thebs.pojo.Hello" scope="prototype">
其余在web开发中使用

6.自动装配

byName:保证所有bean的id唯一,id值要与对象setXxx方法的值xxx一致;如果没有,就报空指针异常。
<bean id="user" class="com.kuang.pojo.User" autowire="byName">
byType:保证所有bean的class唯一,而且class要与注入的属性类型一致
<bean id="user" class="com.kuang.pojo.User" autowire="byType">

使用注解

jdk1.5开始支持注解,spring2.5开始全面支持注解。

①在spring配置文件中引入context文件头

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

②开启属性注解支持!

<context:annotation-config/>

@Autowired是按类型自动转配的,不支持id匹配。
可将类中的set方法去掉,使用@Autowired注解

@Autowired
private Cat cat;

或写在set方法上

@Autowired
public void setCat(Cat cat){
   this.cat = cat;
}

加上@Qualifier则可以根据byName的方式自动装配

@Autowired
@Qualifier(value = "cat2")
private Cat cat;

@Resource默认以byName方式进行装配,也可指定的name属性,不成功再按byType的方式自动装配。都不成功,则报异常。

@Resource(name = "dog1")
private Dog dog;

总结:@Autowired@Resource异同:
同:

它们的作用相同都是用注解方式注入对象,都可以写在字段上,或写在setter方法上。

异:@Autowired默认按类型装配(属于spring规范),@Resource(属于J2EE规范),默认按照名称进行装配,找不到时按类型装配。需要注意的是,如果name属性一旦指定,就只会按照名称进行装配

7.使用注解开发

之前都是使用 bean 的标签进行bean注入,但是实际开发中,我们一般都会使用注解!

<!--指定注解扫描包-->
<context:component-scan base-package="com.thebs"/>

指定包中添加注解

@Component("user")
<!--相当于<bean id="user" class="当前注解的类"/>--> 

@Component的三个衍生注解

@Controller:web层
@Service:service层
@Repository:dao层

属性注入

可不提供set方法,在属性名上添加@value(“值”)
提供了set方法,set方法上添加@value(“值”)

 @Value("猪猪")
 public void setName(String name) {
     this.name = name;
}

自动装配

同上6

作用域

@Scope("prototype")
@Scope("singleton")

JavaConfig

@Component //将这个类标注为Spring的一个组件,放到容器中!

@Component
public class Dog {
    public String name = "dog";
}

@Configuration //代表这是一个配置类

@Configuration  //代表这是一个配置类
public class MyConfig {
    @Bean //通过方法注册一个bean,这里的返回值是Bean的类型,方法名就是bean的id!
    public Dog dog(){
        return new Dog();
    }
}

测试

ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
Dog dog = (Dog) context.getBean("dog");

导入其他配置
@Import(MyConfig2.class)

总结

xml与注解比较:
XML可以适用任何场景 ,结构清晰,维护方便
注解不是自己提供的类使用不了,开发简单方便

xml与注解整合开发 :推荐最佳实践

xml管理Bean
注解完成属性注入
使用过程中,可以不用扫描,扫描是为了类上的注解

代理

①静态代理

//真实业务
UserServiceImpl userService = new UserServiceImpl();
//代理类
UserServiceProxy proxy = new UserServiceProxy();
//使用代理类实现日志功能!
proxy.setUserService(userService);

核心思想:我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想
【聊聊AOP:纵向开发,横向开发】
在这里插入图片描述

②动态代理

分为两类:
基于接口的动态代理——JDK动态代理
基于类的动态代理—cglib

一个动态代理 , 一般代理某一类业务
一个动态代理可以代理多个类,代理的是接口,但只可以代理一个接口
核心 :
InvocationHandler接口:每个代理实例都有一个调用处理程序,实现了此接口。内含invoke()方法
Proxy类:提供创建动态代理类的静态方法

创建抽象角色
创建真实角色
创建代理角色(实现了InvocationHandler接口)
①set方法;②getProxy()方法;③重写invoke方法

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    //生成代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }
    // proxy : 代理类
    // method : 代理类的调用处理程序的方法对象.
    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 s){
        System.out.println("执行了"+s+"方法");
    }
}

测试:
①创建真实对象
②创建代理对象的调用处理程序
③设置代理对象setTarget()
④动态生成代理类getProxy()

public class Test {
    public static void main(String[] args) {
        //真实对象
        UserServiceImpl userService = new UserServiceImpl();
        //代理对象的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService); //设置要代理的对象
        UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
        proxy.delete();
    }
}

AOP

AOP(Aspect Oriented Programming)意为:面向切面编程
在这里插入图片描述

①通过 Spring API 实现
execution表达式:
第一个*任意访问修饰符的方法,第二个*指定类下所有方法,(..)表示任意参数

<!--注册bean-->
	<bean id="userService" class="com.kuang.service.UserServiceImpl"/>
	<bean id="log" class="com.kuang.log.Log"/>
	<bean id="afterLog" class="com.kuang.log.AfterLog"/>
<!--aop的配置-->
    <aop:config>
        <!--切入点  expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

②自定义类来实现Aop

<!--方式二:自定义类-->
    <bean id="diy" class="com.thebs.diy.Diy"/>
    <aop:config>
        <!--自定义切面,ref要引入的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.thebs.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

③使用注解实现

@Aspect
public class Annotation {
 @Before("execution(* com.thebs.service.UserServiceImpl.*(..))")
public void before(){}
<!--方式三:注解-->
    <bean id="annotation" class="com.thebs.diy.Annotation"/>
    <!--开启注解支持-->
    <!--默认false是jdk,true是cglib-->
   <aop:aspectj-autoproxy proxy-target-class="false"/>

Mybatis-Spring

使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.2</version>
</dependency>

要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据源

dao层:整合Mybatis

①编写数据源

<!--DataSource:使用Spring的数据源替换Mybatis的配置 c3p0 druid-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

②sqlSessionFactory

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>

③sqlSessionTemplate

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
需要给接口加实现类

public class UserMapperImpl implements UserMapper{
    //原来我的的所有操作都使用sqlsession来执行,现在用sqlsessionTemplate
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
    @Override
    public List<User> selectUser() {
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }
}

②比起方式1 , 不需要管理SqlSessionTemplate

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    @Override
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}
将实现类注入Spring
<bean id="userMapper" class="com.thebs.mapper.UserMapperImpl">
    <property name="sqlSession" ref="sqlSession"/>
</bean>
<bean id="userMapper1" class="com.thebs.mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
用户调用Spring
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper1", UserMapper.class);

事务管理

确保数据的完整性和一致性

分为:

声明式事务:AOP。将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
编程式事务:需要在代码中进行事务的管理

事务ACID原则:

原子性、一致性、隔离性、持久性

①配置声明式事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

②配置事务的通知

<tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!--给哪些方法配置事务-->
            <!--配置事务的传播特性:new-->
            <tx:attributes>
                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete"/>
                <tx:method name="update"/>
                <tx:method name="query"/>
                <tx:method name="*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

③配置AOP

<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* com.thebs.dao.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

④测试

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值