public class Demo {
public static void main(String[] args) {
ApplicationContext applicationContext = new
AnnotationConfigApplicationContext(MyConfig.class);
//默认单实例对象
Object person = applicationContext.getBean("person");
System.out.println(person);
}
}
@Configuration
class MyConfig{
@Bean
// @Bean(initMethod = "myInit",destroyMethod = "myDestory") //可自定义初始化和销毁方法
public Person person(){
return new Person("id1","lili");
}
}
//Bean初始化和销毁方法,还可以实现接口
class Cat implements InitializingBean,DisposableBean{
@Override
public void destroy() throws Exception {
//销毁方法
}
@Override
public void afterPropertiesSet() throws Exception {
//初始化方法
}
}
// 去掉所有Controller的注解,所以类型是注解,class 是Controller类
@ComponentScan(value = "com.chinaoly",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
})
// 只扫描Controller的注解
@ComponentScan(value = "com.chinaoly", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters = false)
// 给定的类型。只扫描Service,以及子类bean
@ComponentScan(value = "com.chinaoly",includeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {MyService.class})
})
// 自定义过滤规则
//1 class类实现接口TypeFilter
class MyTypeFilter implements TypeFilter{
/**
*
* @param metadataReader 读取到当前正在扫描的类的信息
* @param metadataReaderFactory 可以获得其他任何类的信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前注解类的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
// 参数:String 或 Resource
MetadataReader metadataReader1 = metadataReaderFactory.getMetadataReader("");
return false;
}
}
//2 添加注解
@ComponentScan(value = "com.chinaoly",includeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
})
用来配置 spring bean 的作用域,它标识 bean 的作用域。
默认值是单例
1、singleton:单例模式,全局有且仅有一个实例。在IOC启动时就放到容器中。
2、prototype:原型模式,每次获取 Bean 的时候会有一个新的实例。获得对象,需要注入等时候创建对象。
3、request:request 表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP request 内有效
4、session:session 作用域表示该针对每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效
@Scope
@Bean
public Person person(){
return new Person("id1","lili");
}
懒加载,主要被使用时才会第一次加载
@Lazy
@Bean
public Person person(){
return new Person("id1","lili");
}
// 1 自定义类
class ConA implements org.springframework.context.annotation.Condition{
/**
*
* @param context 判断条件能使用的上下文
* @param metadata 注释信息
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 1 IOC使用的beanfactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2 类加载器
ClassLoader classLoader = context.getClassLoader();
// 3 获取当前环境信息
Environment environment = context.getEnvironment();
// 4 bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
return false;
}
}
// 2 添加注解 @Conditional(ConA.class)
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean),该注解的参数对应的类必须存在,否则不解析该注解修饰的配置类;
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean), 该注解表示,如果存在它修饰的类的bean,则不需要再创建这个bean;可以给该注解传入参数例如@ConditionOnMissingBean(name = “example”),这个表示如果name为“example”的bean存在,这该注解修饰的代码块不执行。
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)
@ConditionalOnProperty是指在application.yml里配置的属性是否为true,其他的几个都是对class的判断
// 类上直接导入,不需要在代码中 @Bean写方法。默认调用的是无参构造,若需要配置或调用有参构造,还需要方法
@Import(Person.class)
// 或者用ImportSelector 自定义导入需要的组件,可实现逻辑
class MyImport implements ImportSelector{
/**
* 返回值,就是导入到容器中的组件全类名
* @param importingClassMetadata 当前标注@Import注解所在类的所有注解信息
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[0];
}
}
// 或者手动注册移除 注册类
class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{
/**
*
* @param importingClassMetadata 当前类的注解信息
* @param registry BeanDefinition注册类
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class);
// registry.registerBeanDefinition("person1",rootBeanDefinition); //手动注册类
// registry.removeBeanDefinition("类全名"); //移除注册类
}
}
// spring整合其他框架,factoryBean用的较多
class PersonFactoryBean implements FactoryBean{
// 返回一个Color对象,这个对象添加到容器中
@Override
public Person getObject() throws Exception {
return new Person();
}
@Override
public Class> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
getBean("personFactoryBean") 获得的是 Person类
getBean("&personFactoryBean") 获得的是 PersonFactoryBean 类
@Value("123")
@Value("${}") // 从yml文件中获取
@Value("#{}") //SpEL
SpEL表达式
class MyValue{
@Value("po")
private String defaultValue;
private String id = "id1";
private Integer age = 1;
// @Value("#{myValue.id}") // bean 的某个属性
// @Value("#{myValue.age+1}") // 运算 + - * / ^ 等都可以
// @Value("#{myValue.id.concat(myValue.age)}") // concat 拼接字符串
// @Value("#{myValue.age == 1 && myValue.id == 'id1'? 'Yes':'No'}") //三目运算符
// @Value("#{myValue.defaultValue ?:'yes'}") //判空的三目运算,如果未空,返回yes,否则返回原值
// 还可以正则
private String name;
// @Value("#{myValue.age == 1}") //关系运算符: == != < > <= >= xml配置中关系运算符: eq ne lt le gt ge
@Value("#{true && true}") // 逻辑运算符 &&/and ||/or !
private Boolean flag;
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "MyValue{" +
"id='" + id + '\'' +
", age=" + age +
", name='" + name + '\'' +
", flag=" + flag +
'}';
}
}
读取配置文件
@PropertySource(value = "classpath:/person.properties")
@Configuration
class PropertyConfig{
@Bean
public Person person(){
return new Person();
}
}
配置文件中:
person.id = 123
person.name = 里斯
可以根据当前环境,动态激活和切换一系列组件的功能。
//默认default,可不写Profile
@Profile("default")
标识一个该类是 Spring MVC controller 处理器,用来创建处理 http 请求的对象。
Spring4 之后加入的注解,原来在 @Controller 中返回 json 需要 @ResponseBody 来配合,如果直接用 @RestController 替代 @Controller 就不需要再配置 @ResponseBody ,默认返回 json 格式。
用于标注业务层组件,说白了就是加入你有一个用注解的方式把这个类注入到 Spring 配置中
spring框架,用来装配 bean,可以写在字段上,set方法上,有参构造器上(可以省略),参数上,传入参数都会从IOC容器中获取
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的 required 属性为 false,例如:@Autowired(required=false)。
java规范,@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,而 @Resource 默认按 byName 自动注入罢了。
@Resource 有两个属性是比较重要的,分是 name 和 type,Spring 将 @Resource 注解的 name 属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。
所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。
如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略
和@primary不能搭配使用
java规范,和autowire一样自动装配,可以和@pimary 搭配,但没有required属性
当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配。
在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
自定义实现aware接口,在创建对象的时候,会调用接口规定的方法注入相关组件
XXXAware =》 XXXProcessor
class MyTest1 implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware
{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println(" ===== "+name); //类全名
}
//解析器
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String str = resolver.resolveStringValue("你好,我是${os.name}");
System.out.println(str);
}
}
类定义处: 提供初步的请求映射信息,相对于 WEB 应用的根目录。
方法处: 提供进一步的细分映射信息,相对于类定义处的 URL。
用于将请求参数区数据映射到功能处理方法的参数上
用来标记缓存查询。
可用用于方法或者类中,当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
用来标记要清空缓存的方法,当这个方法被调用后,即会清空缓存。 @CacheEvict(value=”UserCache”)
用来标记是在项目启动的时候执行这个方法,用来修饰一个非静态的 void() 方法。
也就是 Spring 容器启动时就执行,多用于一些全局配置、数据字典之类的加载。
被 @PostConstruct 修饰的方法会在服务器加载 Servlet 的时候运行,并且只会被服务器执行一次。
PostConstruct 在构造函数之后执行,init() 方法之前执行。PreDestroy() 方法在 destroy() 方法执行执行之后执行。
// Bean 初始化和销毁 方法
// 1 @Bean(initMethod="", destroyMethod="")
// 2 BeanPostProcessor 接口
@Component
class MyService implements BeanPostProcessor {
//初始化调用之前
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//初始化调用之后
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
// 3 @PostConstruct 和 @PreDestroy
// 4 BeanPostProcessor
@Component
class MyService implements BeanPostProcessor {
//初始化调用之前
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//初始化调用之后
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
被 @PreDestroy 修饰的方法会在服务器卸载 Servlet 的时候运行,并且只会被服务器调用一次,类似于 Servlet 的 destroy() 方法。
被 @PreDestroy 修饰的方法会在 destroy() 方法之后运行,在 Servlet 被彻底卸载之前
用于标注数据访问组件,即 DAO 组件
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
默认情况下 Spring MVC 将模型中的数据存储到 request 域中。当一个请求结束后,数据就失效了。
如果要跨页面使用,那么需要使用到 session。
而 @SessionAttributes 注解就可以使得模型中的数据存储一份到 session 域中。
参数:
1、names:这是一个字符串数组。里面应写需要存储到 session 中数据的名称。
2、types:根据指定参数的类型,将模型中对应类型的参数存储到 session 中
3、value:和 names 是一样的。
适用于 bean 属性 setter 方法,并表示受影响的 bean 属性必须在 XML 配置文件在配置时进行填充。否则,容器会抛出一个 BeanInitializationException 异常。
首选装配
====================================================
切入
@Component
@EnableAspectJAutoProxy // 开启基于注解的切面模式
class LogAspects{
// @Before("pubic boolean com/chinaoly/frm/Person.say(String)")//准确方法的传参
// @Before("pubic boolean com.chinaoly.frm.Person.say(..)")//不需要匹配参数类型
// @Before("pubic boolean com.chinaoly.frm.Person.*(..)")//某个类中所有方法
@Pointcut("execution(pubic boolean com.chinaoly.frm.Person.*(..))")
public void pointCut(JoinPoint point){
}
@Before("pointCut()")
public void logStart(){
}
//是否抛异常都会执行
@After("pointCut()")
public void logEnd(){
}
//正常返回执行
@AfterReturning("pointCut()")
public void logReturn(){
}
//出现异常
@AfterThrowing(value = "pointCut()",throwing = "e")
public void logException(Exception e){
}
//环绕,手动推进目标方法运行
@Around("pointCut()")
public void logRound(){}
}