Spring注解版

Spring注解版

一、@Configuration和@Bean注解

public class Person {

    private String name;
    private Integer age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

配置类:

@Configuration
public class ApplicationConfig {

    @Bean
    public Person person(){
        return new Person("lisi",18);
    }
  	/*@Bean("person02")
    public Person person(){
        return new Person("lisi",20);
    }*/

}

对比配置文件:

<?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">
    <bean id = "person" class="com.wzs.entity.Person">
        <property name="name" value="zs"/>
        <property name="age" value="18"/>
    </bean>
</beans>

1.@Configuration:标注在类上,则表明该类是一个配置类,作用类似xml。

2.@Bean:

​ 1)标注在方法上,则表明注册一个组件到ioc容器中。

​ 2)方法的返回值类型代表要注册到容器的类型,代表bean中的class

​ 3)方法名代表注册到ioc的bean的id

​ 4)@Bean写上字符串则可以该表bean的id

配置类测试:

public class ConfigTest {
    public static void main(String[] args) {
        ApplicationContext ioc = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        Person bean = ioc.getBean("person");
        System.out.println(bean);//Person{name='lisi', age=18}
    }
}

二、@ComponentScan注解

1.@ComponentScan注解作用类似于xml中的context:component-scan标签,即作用是包扫描。

2.该注解写在配置类上

3.格式:@ComponentScan(value = “指定要扫描的包名”)

4.配置包扫描的规则:

1)excludeFilters:排除

配置类方式:

@ComponentScan(value ="com.wzs" ,excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)
})
//excludeFilters:表示排除规则
//type:指定排除的类型
//value:指定排除的具体类型


xml方式:

 <context:component-scan base-package="com.wzs">
        <context:exclude-filter type="annotation" 	expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

2)includeFilters:只包含 注意使用时还要加上useDefaultFilters =false来禁用默认规则

配置类的方式:

@ComponentScan(value ="com.wzs" ,includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)
},useDefaultFilters =false )
//includeFilters:表示只包含规则
//type:指定包含的类型
//value:指定包的具体类型

xml方式:

<context:component-scan base-package="com.wzs" use-default-filters="false">
        <context:include-filter  type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

4)@ComponentScan.Filter的type:指定类型

type可以取的值有:
				FilterType.ANNOTATION;(掌握):代表扫描带有注解的

				FilterType.ASSIGNABLE_TYPE;(掌握):代表扫描指定类的

				FilterType.ASPECTJ;

				FilterType.REGEX;

				FilterType.CUSTOM;(掌握):代表扫描自定义规则类的

FilterType.ASSIGNABLE_TYPE:

@ComponentScan(value ="com.wzs" ,includeFilters = {
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = com.wzs.service.MyService.class)
},useDefaultFilters =false )

FilterType.CUSTOM:

使用FilterType.CUSTOM前提是要写自定义规则的类,且该类要实现TypeFilter接口:

public class Myfilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取扫描当前类的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前正在扫描类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前正在扫描类的资源路径
        Resource resource = metadataReader.getResource();
        //获取扫描类的全类名
        String className = classMetadata.getClassName();
        //将指定的类加载到ioc容器中
        if(className.contains("er")){
            return true;
        }
        return false;
    }
}

// return true;加入到容器
//return false;不加入到容器
@ComponentScan(value ="com.wzs" ,includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,value = com.wzs.filter.Myfilter.class)
},useDefaultFilters =false )

本例详解:由于指定的包为“com.wzs",故会扫描该包下的所有类,因此该包下的所有类都会被com.wzs.filter.Myfilter.class处理,如果类名包含”er“,则加入到ioc容器,否则不加入到ioc容器

三、@Scope注解

前景:无论是xml方式加入组件到ioc容器,还是通过注解的方式加入组件到ioc容器,这些组件默认都是单实例的。

1.@Scope注解用在带有@Bean的标签上

2.@Scope注解的取值有:prototype(多实例的)、singleton(单实例的)

配置类的方式给组件赋予单实例或多实例:

 		@Scope("singleton")
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }


 @Scope("prototype")
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }

xml的方式给组件赋予单实例或多实例:

  <bean id = "person" class="com.wzs.entity.Person" scope="singleton" >
        <property name="name" value="zs"/>
        <property name="age" value="18"/>
    </bean>

  <bean id = "person" class="com.wzs.entity.Person" scope="prototype" >
        <property name="name" value="zs"/>
        <property name="age" value="18"/>
    </bean>

无论是xml还是配置文件的方式:

​ 单实例的对象创建是在容器启动的时候创建。

​ 多实例的对象创建是在每次获取到该实例的时候创建。

四、@Lazy注解

前景:懒加载针对的是单实例的bean,容器启动的时候不创建对象,第一次获取bean时加载.

使用:写在@bean方法之上

配置类的形式:

 
		@Lazy
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }

xml的形式:

 <bean id = "person" class="com.wzs.entity.Person" lazy-init = "true" >
        <property name="name" value="zs"/>
        <property name="age" value="18"/>
    </bean>

五、@Conditional注解

写法:写在@Bean方法或@Configuration类之上。

作用:按照一定的条件,注册指定的bean。其实也类似@ComponentScan中的过滤规则。

使用:

1.创建一个实现了Condition接口的类:

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Linux")){//如果当前的操作系统是Linux系统,则将加入到ioc容器中
            return true;
        }
        return false;
    }
}

2.加@Conditional注解

@Conditional(MyCondition.class)
@Bean
public Person person(){
    return new Person("lisi",18);
}

六、@Import注解

@Import注解的作用:导入指定的类到容器中

单个导入类到容器中,默认id是全类名:

@Import(com.wzs.dao.MyDao.class)
@Configuration
public class ApplicationConfig {
}

批量导入类到容器中,默认id是全类名:

方式一:

​ 首先实现ImportSelector接口

public class MySelector  implements ImportSelector {
    //返回的数组封装了加载到ioc容器组件
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return  new String[]{"com.wzs.service.MyService"};
    }
}

然后:

@Import(com.wzs.condition.MySelector.class)
@Configuration
public class ApplicationConfig {
}

方式二:

首先实现ImportBeanDefinitionRegistrar接口:

public class MyDefiniton  implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition bean = new RootBeanDefinition(Person2.class);//注册一个bean
        registry.registerBeanDefinition("person2",bean);//注册到ioc容器中,第一参数指定bean的id,第二个参数指定注册的bean
    }
}

然后:

@Import(com.wzs.condition.MyDefiniton.class)
@Configuration
public class ApplicationConfig {
}

===================================================================================================================================

导入单个bean到ioc容器中:

首先实现FactoryBean接口:

public class MyFactory implements FactoryBean<Person> {
    //返回一个对象并加入到ioc容器中
    @Override
    public Person getObject() throws Exception {
        return new Person("wzs",22);
    }
    //类型
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
    //是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}
@Configuration
public class ApplicationConfig {
    @Bean
    public MyFactory myFactory(){
        return new MyFactory();
    }

}
public static void main(String[] args) {
        ApplicationContext ioc = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        Object bean = ioc.getBean("myFactory");
        System.out.println(bean.getClass());//class com.wzs.entity.Person类型
 
  	//如果就是想要工厂对象的话
    Object bean = ioc.getBean("&myFactory");
    System.out.println(bean.getClass());  //class com.wzs.condition.MyFactory

  
    }

七、bean的生命周期

1.bean的生命周期:

​ bean创建 --》 初始化 —》销毁

2.容器管理bean的生命周期:

我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候调用我们的初始化和销毁方法。

3.具体步骤:

​ 方式一:用@Bean注解,指定初始化和销毁方法

​ 1)自定义初始化和销毁方法

public class User {

    private int id;
    private String name;

    public User() {
        System.out.println("无参构造方法");
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("有参构造方法");
    }

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

    public void destroy(){
        System.out.println("销毁方法");
    }
}

2)指定初始化和销毁方法

  @Bean(initMethod = "init",destroyMethod = "destroy")
    public User user(){
        return new User();
    }

整个调用的过程:构造器 --》初始化 --》容器关闭 --》销毁

方式二:实现InitializingBean, DisposableBean接口

1)重写初始化和销毁方法:

public class Goods implements InitializingBean, DisposableBean {
    public Goods(){
        System.out.println("构造方法Goods()");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁方法destroy()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法afterPropertiesSet()");
    }
}

整个调用的过程:构造器 --》初始化 --》容器关闭 --》销毁

方式三:使用jsr250中的注解:

​ @PostConstruct:在bean创建完成并属性赋值完成后执行的初始化方法。

​ @PreDestroy:在容器销毁bean之前通知进行的清理工作。

public class Animal {
    public Animal(){
        System.out.println("构造方法Animal()");
    }

    @PostConstruct
    public void init(){
        System.out.println("初始化方法init()");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("销毁方法destroy()");
    }
}
@Bean
   public Animal animal(){
        return new Animal();
    }

整个调用的过程:构造器 --》初始化 --》容器关闭 --》销毁

方式四:实现BeanPostProcessor接口,为【所有bean】【初始化方法】【前后】调用的方法

//bean的后置处理器
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean的名字"+beanName+":postProcessBeforeInitialization");
        return bean ;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean的名字"+beanName+":postProcessAfterInitialization");
        return bean;
    }
}
@Configuration
public class ApplicationConfig {

   @Bean
   public Animal animal(){
        return new Animal();
    }
    public MyBeanPostProcessor myBeanPostProcessor(){
       return new MyBeanPostProcessor();
    }

}

整个调用的过程:构造器 --》postProcessAfterInitialization–》初始化 --》postProcessAfterInitialization–》容器关闭 --》销毁。

即使没有初始化和销毁方法,这些方法也会依次被执行

八、@Value注解

@Value的用法,给属性赋值:

1.基本数值 2.可以写SpEl表达式:#{} 3.可以写${},取出配置文件的值,但是要结合@PropertySource注解

对于第三种方式读取配置文件的值需要先加载配置文件,然后才能读取:

@PropertySource(value = {“classpath:/application.properties”}) value指定配置文件的位置;这种方法类似xml中引入外部配置文件<context:property-placeholder location=“classpath:application.properties”/>.

此外还要说的是@Value方式给bean赋值,是通过Setter方法的方式进行赋值的。

九、自动装配

1.spring规范的@Autowire自动装配:

@Autowire:自动装配 默认首先按照类型自动装配,如果ioc容器中存在多个类型,则按照属性名作为id自动装配;

如果想要装配指定的bean,则【额外】还要加上@Qualifer(“id名”)进行装配;

默认自动装配一定要装配上的,那么我们可以修改默认值,如果装配不上,则装配null,方法是@Autowire(required=falue)

@Primary指定默认装配首选装配的bean,这样自动装配的时候,首选装配用@Primary修饰的bean;

2.java规范的@Resouce和@Inject自动装配:

@Resource注解:自动装配默认按照属性名作为id进行自动装配,不支持required=false和@Primary功能;

当然@Resource(“id名”)指定要装配的bean。

@Inject注解:使用该注解需要导入javax.inject的jar;自动装配 默认首先按照类型自动装配,如果ioc容器中存在多个类型,则按照属性名作为id自动装配;支持@Primary,但不支持required=false。

十、针对@Autowire

@Autowire可以标注的位置有:属性、方法、构造器、参数上。

标注在类普通方法上:

​ ioc容器创建该bean时,会自动调用用@Autowire标注的方法,并且为该方法上所有参数(引用类型)进行自动装配;

​ 如果在配置类的方式上将bean加入到ioc容器中,如果加入该bean的方法上存在参数,则也会自动装配。

   @Bean
    public Person person(User user){//User user会自动被装配上
        return new Person();
    }

标注在构造器上:

​ ioc容器创建该bean时,会优先用@Autowird修饰的构造方法创建bean,并为该构造方法的所有参数(引用类型)进行自动装配。

注意:自动装配默认一定要装配上。

十一、Aop的使用

1.创建一个被切面切的逻辑处理类

package com.wzs.service;

/**
 * *  Created by wzs on 2020/8/23
 **/
public class Calculator {

    public int addition(int a,int b){
        return a+b;
    }
    public int substruction(int a,int b){
        return a-b;
    }
    public int multiplication(int a,int b){
        return a-b;
    }
    public int division(int a,int b){
        return a-b;
    }
}

2.创建一个切面类

package com.wzs.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Arrays;

/**
 * *  Created by wzs on 2020/8/23
 **/
@Aspect
public class LogUtils {

    @Pointcut("execution(public int com.wzs.service.Calculator.*(..))")
    public void poinCut(){}

    @Before(value = "poinCut()")
    public void logBefore(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(joinPoint.getSignature().getName()+"方法运行,@before:参数列表:{"+ Arrays.asList(args)+"}");
    }

    @AfterReturning(value = "poinCut()",returning = "result")
    public void logAfterReturning(JoinPoint joinPoint,Object result){
        System.out.println(joinPoint.getSignature().getName()+"方法运行,@AfterReturning:结果:{"+ result+"}");
    }

    @AfterThrowing(value = "poinCut()",throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint,Exception e){
        System.out.println(joinPoint.getSignature().getName()+"方法运行,@AfterReturning:异常原因:{"+ e.getCause()+"}");

    }
    @After(value = "poinCut()")
    public void logAfter(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"方法运行,@After:");

    }
}

3.将被切和切的类加入到容器,同时开启注解的aop模式@EnableAspectJAutoProxy

package com.wzs.config;

import com.wzs.service.Calculator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * *  Created by wzs on 2020/8/23
 **/
@EnableAspectJAutoProxy //开启注解形式的aop 类似 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Configuration
public class AopConfig {
    @Bean
    public Calculator calculator(){
        return new Calculator();
    }
    @Bean
    public LogUtils logUtils(){
        return new LogUtils();
    }
}

十一、声明式事务

1.写事务,添加@Transactional

public class TxService {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Transactional
    public void insert(){
        String sql = "insert into admin(username,password) values(?,?)";
        String substring = UUID.randomUUID().toString().substring(0, 5);
        jdbcTemplate.update(sql,substring,123456);
        System.out.println("插入成功");
        int a = 1/0;

    }
}

2.配置,添加@EnableTransactionManagement

package com.wzs.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * *  Created by wzs on 2020/8/23
 **/
@EnableTransactionManagement//开启注解事务,类似xml中的 <tx:annotation-driven transaction-manager = "tm"/>
@Configuration
@Import(com.wzs.service.TxService.class)
public class TxConfig {
    @Bean
    public DataSource dataSource() throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/girls");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        return dataSource;
    }
    @Bean
    public JdbcTemplate template() throws Exception {
        return new JdbcTemplate(dataSource());
    }
		//配置事务管理器,控制数据源
    public PlatformTransactionManager platformTransactionManager() throws Exception {
        return new DataSourceTransactionManager(dataSource());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值